Godot: Godot crashes on SteamVR initialization

Created on 3 Jan 2018  路  69Comments  路  Source: godotengine/godot

Godot version:
a24dd678fdef632300347df6e32b5b5b687b0e30 (master)

OS/device including version:
fedora 27, gtx 1080, nvidia linux driver 387.34

Issue description:
Godot crashes on SteamVR initialization

Steps to reproduce:

Start openvr and run a godot vr project.

Thread 1 "godot.x11.opt.t" received signal SIGILL, Illegal instruction.
0x0000000000915c77 in Vector<RasterizerStorageGLES3::RenderTarget::Effects::MipMaps::Size>::operator[](int) ()
gdb bt
#0  0x0000000000915c77 in Vector<RasterizerStorageGLES3::RenderTarget::Effects::MipMaps::Size>::operator[](int) ()
#1  0x00000000009c20de in RasterizerSceneGLES3::render_scene(Transform const&, CameraMatrix const&, bool, RasterizerScene::InstanceBase**, int, RID*, int, RID*, int, RID, RID, RID, RID, int) ()
#2  0x00000000016eb0c5 in VisualServerScene::_render_scene(Transform, CameraMatrix const&, bool, RID, unsigned int, RID, RID, RID, int) ()
#3  0x00000000016ed50b in VisualServerViewport::_draw_viewport(VisualServerViewport::Viewport*, ARVRInterface::Eyes) ()
#4  0x000000000161e551 in VisualServerRaster::draw(bool) ()
#5  0x00000000008982f5 in Main::iteration() ()
#6  0x000000000044ea1d in main ()
bug rendering

Most helpful comment

@BastiaanOlij Bingo! Restarting and not focusing the 3D Scene made the trick 馃憤
All working good. Sponza going well on High settings (not ultra) and no server disconnected error.

Thank you :)

All 69 comments

screenshot from 2018-01-03 06-58-52

I think this code is related, but there's no line number in the stack trace.

@BastiaanOlij seems to be up to you

Hello.
I am having a similar problem, and I wasn't sure if I should start a new bug or not, given that my crash seems to be happening in the same place. Here is console output with stack trace:

Running: /home/darkheron/godot/bin/godot.x11.tools.64 --path /home/darkheron/godot_openvr/demo --remote-debug 127.0.0.1:6007 --allow_focus_steal_pid 6896 --position 560,350
Remote Debugger: Connection failed with status: '1', retrying in 1 msec.
Remote Debugger: Connection failed with status: '1', retrying in 10 msec.
Remote Debugger: Connection failed with status: '2', retrying in 100 msec.
No touch devices found
OpenGL ES 3.0 Renderer: GeForce GTX 980 Ti/PCIe/SSE2
GLES3: max ubo light: 409
GLES3: max ubo reflections: 455, ubo size: 144
Construct gdnative interface
ARVR: Registered interface: OpenVR
ARVR: Registered interface: Native mobile
Creating render model resource
OpenVR: initialising OpenVR context
Main OpenVR interface has been initialized
Main render models interface has been initialized.
Creating render model resource
OpenVR: increased use count to 2
OpenVR: increased use count to 3
Found openvr device 1 (vr_controller_vive_1_5)
Found openvr device 2 (lh_basestation_vive)
Found openvr device 3 (lh_basestation_vive)
Found openvr device 4 (vr_controller_vive_1_5)
Primary interface set to: OpenVR
Creating render model resource
OpenVR: increased use count to 4
models: [arrow, dk2_camera, dk2_hmd, generic_controller, generic_hmd, generic_tracker, hard_bounds, laser_pointer, lh_basestation_01_boysandgirls, lh_basestation_02_batman, lh_basestation_03_robin, lh_basestation_vive, lighthouse_ufo, mptam_hmd_model, oculus_cv1_controller_left, oculus_cv1_controller_right, ref_controller, rift_camera, stage, steam_controller_02_freeman, steam_controller_03_gordon, vr_controller_01_mrhat, vr_controller_02_mrhat_puck, vr_controller_05_wireless_b, vr_controller_vive_1_5, {htc}vr_tracker_vive_1_0, {system}arrow, {system}dk2_camera, {system}dk2_hmd, {system}generic_controller, {system}generic_hmd, {system}generic_tracker, {system}hard_bounds, {system}laser_pointer, {system}lh_basestation_01_boysandgirls, {system}lh_basestation_02_batman, {system}lh_basestation_03_robin, {system}lh_basestation_vive, {system}lighthouse_ufo, {system}mptam_hmd_model, {system}oculus_cv1_controller_left, {system}oculus_cv1_controller_right, {system}ref_controller, {system}rift_camera, {system}stage, {system}steam_controller_02_freeman, {system}steam_controller_03_gordon, {system}vr_controller_01_mrhat, {system}vr_controller_02_mrhat_puck, {system}vr_controller_05_wireless_b, {system}vr_controller_vive_1_5]
Releasing render model resource
OpenVR: decreased use count to 3
ERROR: operator[]: FATAL: Index p_index=0 out of size (size()=0)
   At: core/vector.h:138.
handle_crash: Program crashed with signal 4
Dumping the backtrace. Please include this when reporting the bug on https://github.com/godotengine/godot/issues
[1] /lib/x86_64-linux-gnu/libc.so.6(+0x354b0) [0x7fa65883d4b0] (??:0)
[2] Vector<RasterizerStorageGLES3::RenderTarget::Effects::MipMaps::Size>::operator[](int) (/home/darkheron/godot/core/vector.h:138 (discriminator 7))
[3] RasterizerSceneGLES3::render_scene(Transform const&, CameraMatrix const&, bool, RasterizerScene::InstanceBase**, int, RID*, int, RID*, int, RID, RID, RID, RID, int) (/home/darkheron/godot/drivers/gles3/rasterizer_scene_gles3.cpp:4193)
[4] VisualServerScene::_render_scene(Transform, CameraMatrix const&, bool, RID, unsigned int, RID, RID, RID, int) (/home/darkheron/godot/servers/visual/visual_server_scene.cpp:2019)
[5] VisualServerScene::render_camera(Ref<ARVRInterface>&, ARVRInterface::Eyes, RID, RID, Vector2, RID) (/home/darkheron/godot/servers/visual/visual_server_scene.cpp:1692)
[6] VisualServerViewport::_draw_viewport(VisualServerViewport::Viewport*, ARVRInterface::Eyes) (/home/darkheron/godot/servers/visual/visual_server_viewport.cpp:68)
[7] VisualServerViewport::draw_viewports() (/home/darkheron/godot/servers/visual/visual_server_viewport.cpp:279)
[8] VisualServerRaster::draw(bool) (/home/darkheron/godot/servers/visual/visual_server_raster.cpp:105)
[9] VisualServerWrapMT::draw(bool) (/home/darkheron/godot/servers/visual/visual_server_wrap_mt.cpp:104)
[10] Main::iteration() (/home/darkheron/godot/main/main.cpp:1748)
[11] OS_X11::run() (/home/darkheron/godot/platform/x11/os_x11.cpp:2392)
[12] /home/darkheron/godot/bin/godot.x11.tools.64(main+0xd3) [0xe74d49] (/home/darkheron/godot/platform/x11/godot_x11.cpp:56)
[13] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) [0x7fa658828830] (??:0)
[14] /home/darkheron/godot/bin/godot.x11.tools.64(_start+0x29) [0xe74ba9] (??:?)
-- END OF BACKTRACE --

Now, I am very new to godot, having only used it for about 16 hours now, so I might be doing something wrong, but I have been following the instructions provided by the following videos:

Godot porting Sponza to Open VR here https://www.youtube.com/watch?v=hUr9fQNXdUk
Godot OpenVR Part 1 here https://www.youtube.com/watch?time_continue=541&v=v291rMWCMRw
I'm pretty sure I have everything set up in the way which is required from the videos, but there could be something dumb I am doing I suppose. Interestingly, the little SteamVR status window will switch it's status to [APPNAME] before almost instantly switching to [APPNAME] Unresponsive. Not sure if that is helpful or not.

Using Mint 18.2 Nvidia driver 387.34 on a GTX 980 Ti
Steps to reproduce is really just: Start SteamVR, then run a godot VR application using the little play button in the editor. I don't believe it is required to do a export of the project... is it?

Ayway, glad to do whatever is needed to help. Let me know if I should create another seperate issue.

EDIT: Forgot the markdown for the console output.

This crashes in

current_fbo = storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo;

so either mip_maps or sizes is empty.

I'm also having issues with the Sponza demo with my Oculus Rift and latest build of Godot:

Searching for: oculus_cv1_controller_right Found openvr device 1 (rift_camera) Found openvr device 2 (rift_camera) ERROR: ARVRServer::find_by_type_and_id: Condition ' p_tracker_id == 0 ' is true. returned: 0 At: servers\arvr_server.cpp:280

It is weird but it seems to hapen only when I move the controllers into the camera, only moving the headset seems to work fine. Tell me if you need any further help because I'm a Godot and VR lover :)

There were several changes around GDNative that break older builds. Until the GDNative API is fully frozen once 3.0 is officially released you have to use matching builds or weird things happen.

Coppolaemilio, your issue sounds like the one that I fixed before going on holidays. Unfortunately I do all my testing on an Oculus Rift and the Vive does end up surprising me once in a while...

If you clone this github repository: https://github.com/BastiaanOlij/godot-sponza/tree/godot-sponza-vr
you'll find a version of the DLL I build earlier today which works with todays master and if they don't change anything in the next day or so, should work with RC1 which will be released any day now.

@fire not 100% sure about your original issue though, I don't do anything on Linux. If it is with an older build made after karroffel made changes to GDNative that does give really weird crashes because incorrect methods are being called.

There is a whole discussion on compiling on Linux and various issues here: https://github.com/BastiaanOlij/godot_openvr/issues/17
Ben and Christof seem to know what they are doing on Linux.

@BastiaanOlij When I try to run your repo: https://github.com/BastiaanOlij/godot-sponza/tree/godot-sponza-vr I get this error: Invalid call. Nonexistent function 'Mesh' in base 'ARVRController (ovr_controller.tscn::1)'.

Maybe I need to install something else? I think it correlates with this extends ARVRController but not sure... Sorry I can't help better, I'm kinda new to Godot

Been poking around in this a bit now that I am a little more familiar with godot in general. Making a bit of progress. It seems the whole render target is incorrect... I mean the width and height are even 0. I originally thought it just had do do with mipmap generation on linux, but now it looks like something different. Only been at this a couple hours and I'm really just trying to understand the underlying structure of the code but hopefully I can make some more progress today.

Well, I figured out the problem and got it working.... sort of. The problem is that the target render size that is returned via the ARVRInterface class godot_arvr_get_render_targetsize binding is not correct. That is to say, it is queried within the function correctly (ie size is correctly set to 1512,1680), but the return value is hozed upon returning to ARVRInterfaceGDNative::get_render_targetsize ( ie result is all zero ). This causes a massive failure chain as RasterizerStorageGLES3::render_target_set_size sees that the render target size has changed, and correctly clears it, but then the RasterizerStorageGLES3::_render_target_allocate short-circuits because the render target width and height are both 0. This results in the feeding a cleared render target sent to the scene renderer. This seems bad :)
I was able to get the vr working at least by simply hardcoding the values returned from ARVRInterface into the VisualServerViewport::draw_viewports() method as such:

// override our size, make sure it matches our required size // Size2 size = arvr_interface->get_render_targetsize(); // VSG::storage->render_target_set_size(vp->render_target, size.x, size.y); VSG::storage->render_target_set_size(vp->render_target, 1512, 1680);

I have not dug into the types yet to see if godot_vector2 is correctly copyable or not but there is surely something amiss with that code. My brain is killing me and I'll try to figure out a proper fix tomorrow it noone else comes along.

@coppolaemilio which version of godot are you using? this latest DLL will only work with the latest master of Godot which will hopefully soon be released as release candidate 1, I think akien is working on that build as we speak.

@Darkheron this is really strange, I have not seen get_render_targetsize() fail. I would suggest you try and compile the godot_openvr.dll yourself from source and put some output in there to see if its not getting the right values from OpenVR or whether something is going wrong between the calls.
Assuming this isn't another version mismatch. The problem with GDNative is that the API is still in flux and as the API is exchanged between godot and module is exchanged in the form of a struct, it may end up calling the wrong functions when the order of calls in that struct changes.

I already had compiled everything locally, but just to be sure, I have backed up everything and I am recloning both godot and godot_openvr. godot has built successfully, but unfortunately godot_openvr will no longer compile for me with an error:
src/OVRRenderModel.cpp:98:4: error: 'godot_char_string' was not declared in this scope

This is when I noticed that unlike godot, there is a beta2 branch for godot_openvr. Should I be using that branch instead? The godot_openvr readme states:

Note that the master in this repository is lined up with the master godot source

So I assumed that godot master and godot_openvr master were compatible. Now that you mention version mismatch, I'm not sure. What branch should I be using to compile and run against the godot master branch?

Tested godot_openvr on macOS 10.13.2 (17C205), Godot 6a4521d

OpenVR SDK https://github.com/ValveSoftware/openvr/commit/53c417bb16cee003cd949254a2aa00714046efbd built with following settings:
openvr

godot_openvr https://github.com/BastiaanOlij/godot_openvr/commit/02c25bb1f41130abab45ec2b2d1e10d272605d82 built with following changes to the build process:

  • GODOT_HEADERS set to godot source /modules/gdnative/include
  • -std=c++11 added to CCFLAGS
  • LIBPATH changed form [openvr_path + 'lib/' + platform_dir] to [openvr_path + 'bin/' + platform_dir]
  • libopenvr_api.dylib manually copied form openvr/bin/osx64/ to demo/bin/
  • libgodot_openvr.dylib modified with install_name_tool -id to use relative load path: @rpath\libgodot_openvr.dylib
  • libgodot_openvr.dylib modified with install_name_tool -change to use relative dependency search path: @loader_path\libopenvr_api.dylib

I do not have VR device to fully test it, but demo loads and connects to SteamVR.

ARVR: Registered interface: OpenVR
ARVR: Registered interface: Native mobile
Creating render model resource
OpenVR: initialising OpenVR context
Unable to init VR runtime: Hmd Not Found Presence Failed (126)
Compositor initialization failed. See log file for details.

I have been debugging the same issue as the original poster of this issue and @Darkheron,

From what I can see, GetRecommendedRenderTargetSize() from the OpenVR SDK is returning the correct values in my case:

RT height: 1512, RT width: 1680

However, the godot2_vector2_new() function is failing for me, the size vector is all 0:

RT height: 0, RT width: 0

It seems it's not actually assigning any values. Maybe GDNative problem?

EDIT: Even if I assign the values to the already existing size vector via .x and .y, they remain 0. :/

EDIT2: Debugging with GDB, the failure seems to actually be here: https://github.com/godotengine/godot/blob/34c988cfa92f19c232b65990704816ba1c7d2622/modules/gdnative/arvr/arvr_interface_gdnative.cpp#L176

After that, all values seem to be 0.

@bruvzg sweet!! if you haven't already, can you add a PR for your changes on the external?

@beniwtv that is so weird, I'll have a closer look tonight, Karroffel did change a few things in the API, this might be one of them.

With the latest version I managed to get it to work for about 3 seconds, then it crashes and I see this error:

ERROR: read: Server disconnected!

At: drivers/windows/stream_peer_tcp_winsock.cpp:203

@coppolaemilio could be one of the regression issues Akien talked about?

Do note that I've moved the openvr plugin to using openvr 1.0.12 so make sure you also grab the new openvr_api.dll and there are a few changes in the scene files because I was using some variable names that are now reserved (like name) and I had to rename those.

@BastiaanOlij Working great with the latest version! The Sponza demo is very very slow and makes me sick really bad because the screen is jumping all over the place, but if I make a simple 3D scene with a couple of elements it works flawlessly. Is this related to godot's performance? I'm able to play any oculus game on ultra settings since my computer is pretty powerful, but with that sponza model and lights things run very very bad.
Thanks for your work! 馃帀

@coppolaemilio what sort of hardware are you running?

The biggest thing in the Sponza demo is the GI probe which does require a pretty recent GPU to run at full speed. You can improve it by choosing the lower quality level in the menu and by going into your OpenVR settings and reducing the supersampling. You'll notice with many VR games they tent to use simpler lighting models because at the higher frame rate and higher render resolutions it just can't keep up.

I am planning a video on replacing the GI Probe by the new lightmapper which will work much better on slower hardware.

@BastiaanOlij
I have 16GB RAM, GTX 1060 6GB and i5-7500 @ 3.40GHz
The other Sponza demo without the VR is also going kinda slow. Again, I don't have any issues with most games I play, I can even run PUBG (a game famous for being slow) with rock solid 60 FPS no problems.

And yes, I turned off things and it does improve but I'm starting to be skeptical with Godot's performance 馃槱

@coppolaemilio hmmm, doesn't sound to different from my laptop, also have a 1060 but an i7.
It runs pretty smoothly for me.

oh don't forget! make sure the editor is not showing a 3D view as it will be taking a lot of GPU power away from your game just rendering the visuals in the editor

@BastiaanOlij It seems to work much better if I don't have the 3D view opened! Too bad I started getting the drivers/windows/stream_peer_tcp_winsock.cpp:203 - Server disconnected! again on both, the Sponza and my own project

@coppolaemilio try restarting. I think this may be a timing issue or something, not even sure if its related to OpenVR

@BastiaanOlij Bingo! Restarting and not focusing the 3D Scene made the trick 馃憤
All working good. Sponza going well on High settings (not ultra) and no server disconnected error.

Thank you :)

So a little more thorough debugging reveals the error is here:

https://github.com/godotengine/godot/blob/b50a9114b105dafafdda8248a38653bca314a6f3/modules/gdnative/arvr/arvr_interface_gdnative.cpp#L173

Somehow, the "result" variable contains no values - even though if I print just before this line in the interface it contains the correct data:

https://github.com/BastiaanOlij/godot_openvr/blob/master/src/ARVRInterface.cpp#L199

(Make sure to printf as float, else you get strange values, which is what threw me off before).

@BastiaanOlij @karroffel Is there any extra GDNative layer (or wrapper) between those two? Else, I don't quite get how the values aren't returned from the function. Either that, or it's do do with the compiler (or it's flags).

@beniwtv, no, that command should call the function in the GDNative module directly. The variable "interface" is a structure with pointers to function inside of the module. The only thing that can go wrong here is if the definition of this structure does not match the definition inside of the module because your copy of Godot is out of sync with the copy of the module.

Well, the other thing that may be possible here is the definition of float. Godot uses its own type "real_t" for which is typedef'ed to float. There is an option to change this to using double. Obviously if one is defined as double and the other as float things get really troublesome. Though I would expect much bigger problems with many more functions as real_t is heavily used. Still its worth a double check.

I also have an issue that looks related with pull from this afternoon...

if I comment the get_viewport().arvr = true line in the demo I have the position tracking ok with rendering on the godot screen (don't know how to disable that main image btw)

if not godot crash at openvr screen initialisation (lobby turns gray then back to black with crash)

user@user-P65xRP /media/user/39de4a6b-808f-4262-946f-f0a95c61e8df/godot3-beta/godot/bin $ FPS: 1
FPS: 1
FPS: 73
FPS: 88
FPS: 91
Running: /media/user/39de4a6b-808f-4262-946f-f0a95c61e8df/godot3-beta/godot/bin/godot.x11.tools.64 --path /media/user/39de4a6b-808f-4262-946f-f0a95c61e8df/godot3-beta/godot_openvr/godot_openvr/demo --remote-debug 127.0.0.1:6007 --allow_focus_steal_pid 15017 --position 560,290
No touch devices found
OpenGL ES 3.0 Renderer: GeForce GTX 1060/PCIe/SSE2
GLES3: max ubo light: 409
GLES3: max ubo reflections: 455, ubo size: 144
FPS: 33
Construct gdnative interface
ARVR: Registered interface: OpenVR
ARVR: Registered interface: Native mobile
Creating render model resource
OpenVR: initialising OpenVR context
Main OpenVR interface has been initialized
Main render models interface has been initialized.
Creating render model resource
OpenVR: increased use count to 2
OpenVR: increased use count to 3
Found openvr device 1 (lh_basestation_vive)
Primary interface set to: OpenVR
Creating render model resource
OpenVR: increased use count to 4
models: [arrow, dk2_camera, dk2_hmd, generic_controller, generic_hmd, generic_tracker, hard_bounds, laser_pointer, lh_basestation_01_boysandgirls, lh_basestation_02_batman, lh_basestation_03_robin, lh_basestation_vive, lighthouse_ufo, mptam_hmd_model, oculus_cv1_controller_left, oculus_cv1_controller_right, ref_controller, rift_camera, stage, steam_controller_02_freeman, steam_controller_03_gordon, vr_controller_01_mrhat, vr_controller_02_mrhat_puck, vr_controller_05_wireless_b, vr_controller_vive_1_5, {htc}vr_tracker_vive_1_0, {system}arrow, {system}dk2_camera, {system}dk2_hmd, {system}generic_controller, {system}generic_hmd, {system}generic_tracker, {system}hard_bounds, {system}laser_pointer, {system}lh_basestation_01_boysandgirls, {system}lh_basestation_02_batman, {system}lh_basestation_03_robin, {system}lh_basestation_vive, {system}lighthouse_ufo, {system}mptam_hmd_model, {system}oculus_cv1_controller_left, {system}oculus_cv1_controller_right, {system}ref_controller, {system}rift_camera, {system}stage, {system}steam_controller_02_freeman, {system}steam_controller_03_gordon, {system}vr_controller_01_mrhat, {system}vr_controller_02_mrhat_puck, {system}vr_controller_05_wireless_b, {system}vr_controller_vive_1_5]
Releasing render model resource
OpenVR: decreased use count to 3
FPS: 85
ERROR: operator[]: FATAL: Index p_index=0 out of size (size()=0)
At: core/vector.h:138.
handle_crash: Program crashed with signal 4
Dumping the backtrace. Please include this when reporting the bug on https://github.com/godotengine/godot/issues
[1] /lib/x86_64-linux-gnu/libc.so.6(+0x354b0) [0x7f6c6305e4b0] (??:0)
[2] Vector::operator (/media/user/39de4a6b-808f-4262-946f-f0a95c61e8df/godot3-beta/godot/core/vector.h:138 (discriminator 7))
FPS: 93
[3] RasterizerSceneGLES3::render_scene(Transform const&, CameraMatrix const&, bool, RasterizerScene::InstanceBase*, int, RID, int, RID, int, RID, RID, RID, RID, int) (/media/user/39de4a6b-808f-4262-946f-f0a95c61e8df/godot3-beta/godot/drivers/gles3/rasterizer_scene_gles3.cpp:4193)
[4] VisualServerScene::_render_scene(Transform, CameraMatrix const&, bool, RID, unsigned int, RID, RID, RID, int) (/media/user/39de4a6b-808f-4262-946f-f0a95c61e8df/godot3-beta/godot/servers/visual/visual_server_scene.cpp:2018)
FPS: 92
[5] VisualServerScene::render_camera(Ref&, ARVRInterface::Eyes, RID, RID, Vector2, RID) (/media/user/39de4a6b-808f-4262-946f-f0a95c61e8df/godot3-beta/godot/servers/visual/visual_server_scene.cpp:1691)
[6] VisualServerViewport::_draw_viewport(VisualServerViewport::Viewport
, ARVRInterface::Eyes) (/media/user/39de4a6b-808f-4262-946f-f0a95c61e8df/godot3-beta/godot/servers/visual/visual_server_viewport.cpp:68)
FPS: 89
[7] VisualServerViewport::draw_viewports() (/media/user/39de4a6b-808f-4262-946f-f0a95c61e8df/godot3-beta/godot/servers/visual/visual_server_viewport.cpp:279)
FPS: 91
[8] VisualServerRaster::draw(bool) (/media/user/39de4a6b-808f-4262-946f-f0a95c61e8df/godot3-beta/godot/servers/visual/visual_server_raster.cpp:105)
[9] VisualServerWrapMT::draw(bool) (/media/user/39de4a6b-808f-4262-946f-f0a95c61e8df/godot3-beta/godot/servers/visual/visual_server_wrap_mt.cpp:104)
[10] Main::iteration() (/media/user/39de4a6b-808f-4262-946f-f0a95c61e8df/godot3-beta/godot/main/main.cpp:1750)
FPS: 90
[11] OS_X11::run() (/media/user/39de4a6b-808f-4262-946f-f0a95c61e8df/godot3-beta/godot/platform/x11/os_x11.cpp:2392)
[12] /media/user/39de4a6b-808f-4262-946f-f0a95c61e8df/godot3-beta/godot/bin/godot.x11.tools.64(main+0xd3) [0xe7b539] (/media/user/39de4a6b-808f-4262-946f-f0a95c61e8df/godot3-beta/godot/platform/x11/godot_x11.cpp:56)
[13] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) [0x7f6c63049830] (??:0)
FPS: 92
[14] /media/user/39de4a6b-808f-4262-946f-f0a95c61e8df/godot3-beta/godot/bin/godot.x11.tools.64(_start+0x29) [0xe7b399] (??:?)
-- END OF BACKTRACE --
Nothing read: Connection reset by peer
ERROR: read: Server disconnected!

At: drivers/unix/stream_peer_tcp_posix.cpp:276.
FPS: 79
FPS: 89

That crash is something I need to investigate more. If you do not set arvr to true on the main viewport, that viewport should render as normal using whatever camera is available. This way you could add a spectator camera to your environment or simply render some 2D stuff to your main viewport.

However, you still need a viewport for your openvr stuff so you need to add a viewport to your scene and add your ARVR stuff as child nodes to that viewport, then turn ARVR to true on that viewport.

This will cause godot to render to that viewport (which you're not displaying) and redirect the output to the HMD.

I haven't tested this though so no idea if it works as intended. Still on my list of todos ;)

@Olm-e Yep, is the same crash a few of us are getting on Linux. Setting get_viewport().arvr = true obviously prevents the crash, as the crash is directly tied to the code currently not setting any size for the render target of the viewport, which crashes the GLES3 renderer.

@beniwtv is that crash reproducable outside of OpenVR? i.e. if you add a viewport to the scene and don't initialise the size, does it crash?

The main viewport should always have a size as it gets its size from the window. With ARVR off on the main viewport and there not being any viewports added to your scene, there simply should be no rendering to the HMD. Defo shouldn't crash...

Well, after 3 days of no power from snowstorms I finally got back around to looking at this a bit today. A little bummed we are still at the same spot diagnostically :)

Completely removed everything that was currently on my machine and started with fresh downloads from both godot and godot_openvr. To make sure the headers weren't mismatched, I didn't even bother with the ones from this repository and just set GODOT_HEADERS to the directory inside of the main godot distribution. Still get the same error though. Only have had a bit to look at it, but there are different godot_vector2 structure definitions in each repository as revealed by gdb ptype. A cursory glance at them and it seems they should be fine ( I don't think alignment would be an issue), but something bad is happening to that return value and that is all I can see for now. Hopefully get some more time tomorrow. The question is why would this work on windows but not linux.

PS: any chance we can get the scons platform selector argument changed to "x11" instead of "linux" like in the main distro for the sake of consistency?

just an idea : couldn't it be a nullptr lost in the wood because of some -std=c++11 missing flags somewhere ? (had the problem at compilation with blender_openvr, found in error functions in openvr... replaced by 0 by gcc if > c++11)

@Darkheron put in a PR for changing it to x11, I'm happy for it to change but not having a linux environment to test I'd rather have some who does test it and submit the change.

@Olm-e very possible, so far this bug makes no sense at all especially since this has worked in the past. I'm not even 100% sure if the c++11 flag is really needed...

Btw, just so everyone knows. In GDNative all Godot structures are defined as byte arrays. This is purely because most of these are C classes but you can't call their methods directly from the module.

Because not being able to access the members of vectors directly is a nuicense Karroffel did create the option to overrule this and actually define the vector classes properly which I use.

All in all this shouldn't matter as long as the sizes are the same.

So @BastiaanOlij and I did some more debugging on IRC/Matrix, and couldn't figure out why the data somehow goes missing when casting the structs. I thought about stuff like alignment problems and whatnot, but then:

Out of curiosity, I compiled Godot and godot_openvr with LLVM/Clang (command line option use_llvm=yes when compiling), and the crash is gone and tracking works!

Not sure if the official binaries for RC3 were compiled on LLVM on Linux, but that version now also works with the compiled godot_openvr module!

If anyone has any more experience with GCC, and has an idea what might be going on, let me know ;)

Sounds like a job for @hpvb, our compiler-specific bug hunter ;)

With clang-svn 7.0.0svn_r323304 I still get the same crash.
There are also gl errors just before the crash.

Mesa: User error: GL_INVALID_OPERATION in glBindFramebuffer(buffer)
Mesa: 1 similar GL_INVALID_OPERATION errors
Mesa: User error: GL_INVALID_OPERATION in glReadBuffer(invalid buffer GL_COLOR_ATTACHMENT0)
ERROR: operator[]: FATAL: Index p_index=0 out of size (size()=0)
   At: core/vector.h:138.
handle_crash: Program crashed with signal 4
Dumping the backtrace. Please include this when reporting the bug on https://github.com/godotengine/godot/issues
[1] /usr/lib/libc.so.6(+0x348e0) [0x7fd6bdf808e0] (??:0)
[2] Vector<RasterizerStorageGLES3::RenderTarget::Effects::MipMaps::Size>::operator[](int) (/home/chris/oldhome/build/godot/core/vector.h:138)
[3] RasterizerSceneGLES3::render_scene(Transform const&, CameraMatrix const&, bool, RasterizerScene::InstanceBase**, int, RID*, int, RID*, int, RID, RID, RID, RID, int) (/home/chris/oldhome/build/godot/drivers/gles3/rasterizer_scene_gles3.cpp:4193)
[4] VisualServerScene::_render_scene(Transform, CameraMatrix const&, bool, RID, unsigned int, RID, RID, RID, int) (/home/chris/oldhome/build/godot/servers/visual/visual_server_scene.cpp:2018)
[5] VisualServerScene::render_camera(Ref<ARVRInterface>&, ARVRInterface::Eyes, RID, RID, Vector2, RID) (/home/chris/oldhome/build/godot/servers/visual/visual_server_scene.cpp:1691)
[6] VisualServerViewport::_draw_viewport(VisualServerViewport::Viewport*, ARVRInterface::Eyes) (/home/chris/oldhome/build/godot/servers/visual/visual_server_viewport.cpp:68)
[7] VisualServerViewport::draw_viewports() (/home/chris/oldhome/build/godot/servers/visual/visual_server_viewport.cpp:278)
[8] VisualServerRaster::draw(bool) (/home/chris/oldhome/build/godot/servers/visual/visual_server_raster.cpp:105)
[9] VisualServerWrapMT::draw(bool) (/home/chris/oldhome/build/godot/servers/visual/visual_server_wrap_mt.cpp:104)
[10] Main::iteration() (/home/chris/oldhome/build/godot/main/main.cpp:1750)
[11] OS_X11::run() (/home/chris/oldhome/build/godot/platform/x11/os_x11.cpp:2392)
[12] /home/chris/oldhome/build/godot/bin/godot.x11.tools.64.llvm(main+0x140) [0x1007b50] (/home/chris/oldhome/build/godot/platform/x11/godot_x11.cpp:55)
[13] /usr/lib/libc.so.6(__libc_start_main+0xea) [0x7fd6bdf6cf4a] (??:0)
[14] /home/chris/oldhome/build/godot/bin/godot.x11.tools.64.llvm(_start+0x2a) [0x100794a] (??:?)
-- END OF BACKTRACE --

@ChristophHaag I used LLVM 5.0.1, the one in Manjaro's repos, if it makes any difference. Also double-check you make a clean compile with LLVM of the godot_openvr repo.

If that doesn't work, then it might be a problem with new compilers doing something different vs. older compilers. I think Manjaro is currently on GCC 7.2.1 or something (will double-check later).

ok... I can confirm that compiling both godot and godot_openvr with use_llvm=yes option and clang 3.8 - llvm 5.0 on linux mint 18.2 works ...
it compile and headset and controllers work fine \o/
probably something to look at in the depth of compilers (maybe also openvr base bin blob)
but I can finally count on developing content now ;)
(and framerate seems good ... ;) )

so much thanks to you all, that's awesome :)

(hope it doesn't break anymore now... :p - and then maybe I can do a small demo at godotcon ? ... hum ... let's see... )

@Olm-e Nice to hear it works! I'm also at GodotCon, unfortunately, I can't bring any hardware (unfortunately last minute events prevent me from attending this year :(, but if you can give demos it would be really cool!

Never got this working unfortunately. We have tried all the suggestions mentioned to no avail and thus at the moment we are just using hard coded values to test our engine extensions. @Olm-e how are you compiling with clang 3.8 but llvm 5.0? Are you using a custom built version of clang?

We set up a bare bones Mint 18.3 XFCE machine and then tried all versions of clang 3.8 through 5.01, making sure at each step that all other versions of llvm were removed from the machine, as verified by dpkg -l | grep llvm... the exception being the 5.0 libraries required by many packages inside of the Mint 18.3 XFCE. We even went so far as to remove any possible cross contamination by removing all alternatives, and placing a fully contained llvm installation into /etc then setting the PATH into that directory*. Kinda out of ideas now, unless I can figure out the procedure to try as Olm-e suggests and compile with the 3.8 clang frontend while using the 5.0 llvm binaries. We are still evaluating whether or not godot will suit our needs spending time learning the engine and taking a first pass at the vr extensions we will need. It looks promising, so we may get back to this, but for now we will continue with the hardcoded values. In the end this is probably going to end up being something like a compiler flag or something silly like that :)

*Incidentally, removing all alternatives/compiler links in order to rely on a compiler in a PATH breaks the godot_openvr scons build, but not the main godot build. This is because the godot SConstruct takes into account the user path as such:
env.AppendENVPath('PATH',os.getenv('PATH'))
Prehaps the godot_openvr SConstruct should do the same, if even just to be consistent with the godot scons procedure.

@Darkheron Did you check official 3.0 binaries from the Godot website + OpenVR module in the asset library? I'd be interested to know if you can get that combination to work.

@beniwtv I'll try them tomorrow, but we wish to extend the engine so while that will be an interesting test, we still need to get it to run properly when complied locally. It's not a huge deal atm since we can test and run just fine with the hard coded values. Everything else seems to work without a hitch... it's just that one single call so far which is very bizarre.

EDIT: @beniwtv Using the prebuilts works perfectly. Also, using a custom built godot + the prebuilt OpenVR module works perfectly so far as well. So I guess we are in good shape as long as the OpenVR module is maintained. Thanks.

So a little more thorough debugging reveals the error is here:

godot_vector2 result = interface->get_render_targetsize(data); 

Somehow, the "result" variable contains no values - even though if I print just before this line in the interface it contains the correct data:

I can confirm this, size is not transferred correctly. I have added printfs to both get_render_targetsize in Godot, and godot_arvr_get_render_targetsize in library and got:

640.000000 512.000000 (set in library)
-94881787373816911633580032000.000000 0.000000 (received by godot)

Form Godot side godot_vector2 is defined as struct {uint8_t[8]} - gdnative/vector2.h, and from library side as struct {float, float} - GodotCalls.h.

Changing gdnative/vector2.h definition to struct {float, float} fix the crash.

diff --git a/modules/gdnative/include/gdnative/vector2.h b/modules/gdnative/include/gdnative/vector2.h
index af97524da..9b09dd96d 100644
--- a/modules/gdnative/include/gdnative/vector2.h
+++ b/modules/gdnative/include/gdnative/vector2.h
@@ -42,7 +42,9 @@ extern "C" {
 #ifndef GODOT_CORE_API_GODOT_VECTOR2_TYPE_DEFINED
 #define GODOT_CORE_API_GODOT_VECTOR2_TYPE_DEFINED
 typedef struct {
-   uint8_t _dont_touch_that[GODOT_VECTOR2_SIZE];
+   float x;
+   float y;
 } godot_vector2;
 #endif

Some calling conventions (at least System V AMD64 ABI used on macOS and Linux, IIRC 32-bit cdecl always return struct on stack) doesn't have strict rules for struct return and compiler decides to do it differently for different struct (even when both Godot and library were built with same compiler).

Probably some aspects of gdnative should be reconsidered, and struct returns should be avoided.

Yeah, that confirms our suspicions about some compilers not returning the struct properly. Nice!
I guess you're right in that struct returns should be avoided.

Looks like this is fatal flaw for GDNative in general, there are tons of struct returns, cc @karroffel.

Well, the API is stable now, not much I can do about it. Would having function attributes help here? Maybe making specific calling conventions explicit could help?

It's not really my fault that compilers are buggy/inconsistent when it comes to struct returns, as struct returns are well defined by the C specification AFAIK.

Would having function attributes help here?

Unlikely, it's already same convention. And compiler actually works according to calling convention specification, both System V ABI and MS ABI use RAX, RDX for integer returns and XMM0, XMM1 for floats. Probably struct should have real definition instead of uint8_t[].

I guess renaming godot_vector2 definition in godot_openvr/src/GodotCalls.h and casting it uint8_t[] struct before return will also work.

For now proper fix would be get rid of struct redefinitions and use callbacks:

diff --git a/src/ARVRInterface.cpp b/src/ARVRInterface.cpp
index 7dc74e0..dd9173d 100644
--- a/src/ARVRInterface.cpp
+++ b/src/ARVRInterface.cpp
@@ -279,18 +279,23 @@ void godot_arvr_commit_for_eye(void *p_data, godot_int p_eye,
    if (p_eye == 1 && !api->godot_rect2_has_no_area(&screen_rect)) {
        // blit as mono, attempt to keep our aspect ratio and center our render buffer
        godot_vector2 render_size = godot_arvr_get_render_targetsize(p_data);
+       godot_vector2 screen_position = api->godot_rect2_get_position(&screen_rect);
+       godot_vector2 screen_size = api->godot_rect2_get_size(&screen_rect);

-       float new_height = screen_rect.size.x * (render_size.y / render_size.x);
-       if (new_height > screen_rect.size.y) {
-           screen_rect.position.y = (0.5 * screen_rect.size.y) - (0.5 * new_height);
-           screen_rect.size.y = new_height;
+       float new_height = api->godot_vector2_get_x(&screen_size) * (api->godot_vector2_get_y(&render_size) / api->godot_vector2_get_x(&render_size));
+       if (new_height > api->godot_vector2_get_y(&screen_size)) {
+           api->godot_vector2_set_y(&screen_position, (0.5 * api->godot_vector2_get_y(&screen_size)) - (0.5 * new_height));
+           api->godot_vector2_set_y(&screen_size, new_height);
        } else {
-           float new_width = screen_rect.size.y * (render_size.x / render_size.y);
+           float new_width = api->godot_vector2_get_y(&screen_size) * (api->godot_vector2_get_x(&render_size) / api->godot_vector2_get_y(&render_size));

-           screen_rect.position.x = (0.5 * screen_rect.size.x) - (0.5 * new_width);
-           screen_rect.size.x = new_width;
+           api->godot_vector2_set_x(&screen_position, (0.5 * api->godot_vector2_get_x(&screen_size)) - (0.5 * new_width));
+           api->godot_vector2_set_x(&screen_size, new_width);
        };

+       api->godot_rect2_set_position(&screen_rect, &screen_position);
+       api->godot_rect2_set_size(&screen_rect, &screen_size);
+
        // printf("Blit: %0.2f, %0.2f - %0.2f, %0.2f\n",screen_rect.position.x,screen_rect.position.y,screen_rect.size.x,screen_rect.size.y);

        arvr_api->godot_arvr_blit(0, p_render_target, &screen_rect);
diff --git a/src/GodotCalls.h b/src/GodotCalls.h
index 7637967..2ac8613 100644
--- a/src/GodotCalls.h
+++ b/src/GodotCalls.h
@@ -5,37 +5,6 @@
 #ifndef GODOT_CALLS_H
 #define GODOT_CALLS_H

-// fully define these, don't waste time with needless callbacks for access
-#define GODOT_CORE_API_GODOT_VECTOR2_TYPE_DEFINED
-typedef struct {
-   float x;
-   float y;
-
-   inline void set(float p_x, float p_y) {
-       x = p_x;
-       y = p_y;
-   };
-} godot_vector2;
-
-#define GODOT_CORE_API_GODOT_VECTOR3_TYPE_DEFINED
-typedef struct {
-   float x;
-   float y;
-   float z;
-
-   inline void set(float p_x, float p_y, float p_z) {
-       x = p_x;
-       y = p_y;
-       z = p_z;
-   };
-} godot_vector3;
-
-#define GODOT_CORE_API_GODOT_RECT2_TYPE_DEFINED
-typedef struct {
-   godot_vector2 position;
-   godot_vector2 size;
-} godot_rect2;
-
 #include <gdnative_api_struct.gen.h>

 #include <stdint.h>

Guys, we need to solve this properly. There is no reason why the struct redefinitions shouldn't work. you compile Godot with those compilers, you compile the gdnative module with that compiler. We must be missing some compiler setting that makes that one compiler fail. It works on all other compilers, it works on Mac, it works on Windows. Let's not screw our system just because one compiler on Linux is not playing ball.

Using access methods to do something basic as setting a float in a struct is unnecessary overhead. This is going to cause a lot of performance issues on more performance sensitive areas such as parsing the render models on OpenVR.

I'm very much against this solution @bruvzg , We need to find out why this compiler is giving us a hard time and solve it properly, not handicap ourselves.

you compile Godot with those compilers, you compile the gdnative module with that compiler.

Just noting that we can't guarantee that GDNative modules will be compiled for each platform with the same toolchain that the Godot templates were (actually, I can guarantee they most certainly won't). So we need to be sure that compiled modules play nice with the Godot runtime output by another compiler.

it works on Mac

It doesn't, even with same compiler and same optimisation options.


https://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf - Check 3.2.3 (pages 18-28), If I understand it correctly compiler works as expected and struct redefinition shouldn't work.

We have definition "A":

#define GODOT_VECTOR2_SIZE 8

typedef struct {
    uint8_t _dont_touch_that[GODOT_VECTOR2_SIZE];
} godot_vector2;

Redefine as "B":

typedef struct {
    float x;
    float y;

    inline void set(float p_x, float p_y) {
        x = p_x;
        y = p_y;
    };
} godot_vector2;

(Page 18) "The classification of aggregate"

Both "A" and "B" are not larger than four eightbytes, and don't have non-trivial copy constructor or non-trivial destructor ==> Each field of an object is classified recursively so that always two fields are considered. If both classes are equal, this is the resulting class.

(Page 17) "Classification"

Struct "A" ==> uint8_t is in INTEGER class. All fields are INTEGER --> Struct is INTEGER class.
Struct "B" ==> float is in SSE class. All fields are SSE --> Struct is SEE class.

(Page 22) "Returning of Values"

Struct "A" ==> If the class is INTEGER, the next available register of the sequence %rax, %rdx is used.
Struct "B" ==> If the class is SSE, the next available vector register of the sequence %xmm0, %xmm1 is used.


Using access methods to do something basic as setting a float in a struct is unnecessary overhead.
This is going to cause a lot of performance issues on more performance sensitive areas such as parsing the render models on OpenVR.

I guess having both definitions and reinterpret_cast it back and forth should have near zero cost, but code will become far less readable.

I think @bruvzg tested on Mac previously without HMD - without HMD the code in question isn't used, so there is no crash, it only triggers when an HMD is connected.

I think @bruvzg tested on Mac previously without HMD - without HMD the code in question isn't used, so there is no crash, it only triggers when an HMD is connected.

Yep I previously tested it "Null Driver" (fake HMD) was crashing Steam and I only tested it without HMD.

System V ABI: The classification of aggregate (structures and arrays) and union types
(e) If one of the classes is INTEGER, the result is the INTEGER

Since INTs is higher priority, adding unions to redefinitions in GodotCalls.h works on macOS:

#include <stdint.h>

// fully define these, don't waste time with needless callbacks for access
#define GODOT_CORE_API_GODOT_VECTOR2_TYPE_DEFINED
typedef union {
    //Force struct to be classified as INTEGER by System V ABI.
    uint8_t _dont_touch_that[8];
    struct {
        float x;
        float y;
    };

    inline void set(float p_x, float p_y) {
        x = p_x;
        y = p_y;
    };
} godot_vector2;

#define GODOT_CORE_API_GODOT_VECTOR3_TYPE_DEFINED
typedef union {
    //Force struct to be classified as INTEGER by System V AMD64 ABI.
    uint8_t _dont_touch_that[12];
    struct {
        float x;
        float y;
        float z;
    };

    inline void set(float p_x, float p_y, float p_z) {
        x = p_x;
        y = p_y;
        z = p_z;
    };
} godot_vector3;

This should work on Linux as well, but I still think proper solution is changing GDNative APIs, getting rid of all struct returns and pass pointer to caller allocated struct as function argument instead. That's what's happening for bigger structs under the hood anyway.

@bruvzg interesting work around...

I really don't get it though, what is it that destroys the structs? Its just memory being copied? Is it that the actual floats are different or is there something weird in how it copies the data? Or is it some memory alignment issue?

I have no problem with changing the get_render_targetsize to take a pointer as a parameter instead of it returning a struct similar to how godot_arvr_fill_projection_for_eye works. That however will be a breaking change of the API. I rather find out what is causing the struct return to fail and fix it. This whole thing makes zero sense. They are bits of data, the fact that it works when that data is integers but fails when they are floats doesn't make sense. Unless there is something different with the floats themselves but then everything should break seeing we use floats heavily.

I really don't get it though, what is it that destroys the structs? Its just memory being copied? Is it that the actual floats are different or is there something weird in how it copies the data? Or is it some memory alignment issue?

It's too small (< 256 bits) and is returned in registers not in memory, int's go to general purpose RX registers and floats packed to SSE XMM. Library put floats to XMM, Godot want ints and read RX.

@bruvzg ah, that makes sense, that sounds like an optimisation in how its returning data assuming that whatever function calls this is aware of said optimisation. Off course this being between two individually maintained and compiled pieces of code that can't be guaranteed. There has to be a way to inform the compiler the function is designed to be called from outside so it returns the data as is.

I's not compiler specific optimisation, but ABI specification. Both lib and godot follow same data type classification algorithm from https://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf

I don't think it's controllable and I don't see any reasons why redefined structs should be compatible (Is there any C specific docs claim it should?).

@bruvzg ahh, so the problem is that while Vector3 is defined as a struct with 3 floats, because godot_vector3 isn't on the godot side, but is on the gdnative side, it screws up because it uses a different set of registers to pass these structs?

Hey @karroffel that is interesting, it's starting to make sense now. That does make it fairly dangerous to redefine. Is there any argument why we can't define the most basic of gdnative structures (godot_vector2, godot_vector3) with their proper data structure? I get why the more complex ones aren't especially when we have structs in structs or pointers to class instances in structs, but for these simpler ones we may want to make an exception for convenience sake.

@bruvzg btw i like your union work around so feel free to update your PR with that if you haven't already.

@bruvzg ahh, so the problem is that while Vector3 is defined as a struct with 3 floats, because godot_vector3 isn't on the godot side, but is on the gdnative side, it screws up because it uses a different set of registers to pass these structs?

Yep I'm pretty sure functions and data type should be defined in exactly same way on both sides to compatible. Different definitions cause different processing.

btw i like your union work around so feel free to update your PR with that if you haven't already.

Union workaround works with System AMD64 ABI (64-bit Linux and macOS), but it is ABI specific hack, I'm not sure it won't break Windows build or 32-bit builds.

Probably it's better to define separate type with floats an reinterpret_cast to it when internal structure access is required. In this case function definitions will be identical and it should be completely portable.

Something like (also tested on macOS):

diff --git a/src/ARVRInterface.cpp b/src/ARVRInterface.cpp
index 7dc74e0..add0a81 100644
--- a/src/ARVRInterface.cpp
+++ b/src/ARVRInterface.cpp
@@ -274,26 +274,27 @@ void godot_arvr_commit_for_eye(void *p_data, godot_int p_eye,
    // of one of the eyes to the main viewport if p_screen_rect is set, and only
    // output to the external device if not.

-   godot_rect2 screen_rect = *p_screen_rect;
+   godot_rect2_internal *screen_rect = reinterpret_cast<godot_rect2_internal *>(p_screen_rect);

-   if (p_eye == 1 && !api->godot_rect2_has_no_area(&screen_rect)) {
+   if (p_eye == 1 && !api->godot_rect2_has_no_area(reinterpret_cast<godot_rect2 *>(screen_rect))) {
        // blit as mono, attempt to keep our aspect ratio and center our render buffer
-       godot_vector2 render_size = godot_arvr_get_render_targetsize(p_data);
+       godot_vector2 __render_size = godot_arvr_get_render_targetsize(p_data);
+       godot_vector2_internal *render_size = reinterpret_cast<godot_vector2_internal *>(&__render_size);

-       float new_height = screen_rect.size.x * (render_size.y / render_size.x);
-       if (new_height > screen_rect.size.y) {
-           screen_rect.position.y = (0.5 * screen_rect.size.y) - (0.5 * new_height);
-           screen_rect.size.y = new_height;
+       float new_height = screen_rect->size.x * (render_size->y / render_size->x);
+       if (new_height > screen_rect->size.y) {
+           screen_rect->position.y = (0.5 * screen_rect->size.y) - (0.5 * new_height);
+           screen_rect->size.y = new_height;
        } else {
-           float new_width = screen_rect.size.y * (render_size.x / render_size.y);
+           float new_width = screen_rect->size.y * (render_size->x / render_size->y);

-           screen_rect.position.x = (0.5 * screen_rect.size.x) - (0.5 * new_width);
-           screen_rect.size.x = new_width;
+           screen_rect->position.x = (0.5 * screen_rect->size.x) - (0.5 * new_width);
+           screen_rect->size.x = new_width;
        };

        // printf("Blit: %0.2f, %0.2f - %0.2f, %0.2f\n",screen_rect.position.x,screen_rect.position.y,screen_rect.size.x,screen_rect.size.y);

-       arvr_api->godot_arvr_blit(0, p_render_target, &screen_rect);
+       arvr_api->godot_arvr_blit(0, p_render_target, reinterpret_cast<godot_rect2 *>(screen_rect));
    };

    if (arvr_data->ovr != NULL) {
diff --git a/src/GodotCalls.h b/src/GodotCalls.h
index 7637967..b5acb88 100644
--- a/src/GodotCalls.h
+++ b/src/GodotCalls.h
@@ -6,7 +6,6 @@
 #define GODOT_CALLS_H

 // fully define these, don't waste time with needless callbacks for access
-#define GODOT_CORE_API_GODOT_VECTOR2_TYPE_DEFINED
 typedef struct {
    float x;
    float y;
@@ -15,9 +14,8 @@ typedef struct {
        x = p_x;
        y = p_y;
    };
-} godot_vector2;
+} godot_vector2_internal;

-#define GODOT_CORE_API_GODOT_VECTOR3_TYPE_DEFINED
 typedef struct {
    float x;
    float y;
@@ -28,13 +26,12 @@ typedef struct {
        y = p_y;
        z = p_z;
    };
-} godot_vector3;
+} godot_vector3_internal;

-#define GODOT_CORE_API_GODOT_RECT2_TYPE_DEFINED
 typedef struct {
-   godot_vector2 position;
-   godot_vector2 size;
-} godot_rect2;
+   godot_vector2_internal position;
+   godot_vector2_internal size;
+} godot_rect2_internal;

 #include <gdnative_api_struct.gen.h>

This is less readable, but should work with any ABI and compiler. And reinterpret_cast should have zero cost.

@bruvzg are you worried that the union approach won't work on every compiler?
This looks far more ugly...

@bruvzg are you worried that the union approach won't work on every compiler?
This looks far more ugly...

Should be tested to be sure, but most likely it's fine for all OpenVR module targets (at least looks OK after quick specifications check: Windows only care about struct size on both x86 and x86-64, x86 Linux always use memory, arm/aarch64 Linux EABI looks compatible too). It's just not guaranteed to be portable to every exotic platform.

@bruvzg better then it was imho :) I'll test it when I'm home to see if it doesn't give me any troubles and if not it'll be merged and applied to the other repos as well to prevent future issues :)

I think the fix to this problem is not to break the whole API and change struct returns to out-parameter pointers but instead just not allow the overwriting of those types. If direct (possibly) unsafe access is desired on the library side then a library-side conversion union should be used instead.

@karroffel feels like a step backwards but I do agree, if its unsafe then its not going to help anyone.
That said, the union solution brugzg came up with does seem to solve the issue. I still put question marks by whether core types like godot_vector2 and godot_vector3 shouldn't just be defined with proper members on the Godot side. I get the argument for more complex types, but not for core types like these.

I find this a hard one, the whole reason for GDNative is to create a bridge to C++ to deal with those situations where the performance of C++ is needed. To do something as simple as working with the x, y or z members of a vector, often doing multiple accesses to perform an action, and then have to deal with function calls.....
We are talking about use cases where we'll likely be processing large volumes of data such as looping through millions of vertices as we're performing functions on meshes and such.

It seems counter intuitive to handicap ourselves like this.

Was this page helpful?
0 / 5 - 0 ratings