Keyboarder
Topic Author
Posts: 21
Joined: 21 Oct 2014, 11:57

Qt binding

19 Jan 2017, 10:06

We are trying to make Qt binding for NoesisGui and we ran into a problem.
The test binding code is being built upon Qt OpenGL example code: https://doc.qt.io/qt-5/qtgui-openglwindow-example.html
The app runs with very high CPU usage and crashes when closing. Do you maybe have any suggestions on how to overcome this problem?


From previous thread:
Also I need more information about the crash. Is the rendering output correct?
Yes, rendering output is correct but the CPU usage is very high. This is probably because Qt executes everything within the main thread. I've tried to put rendering device on the separate thread without any success. Also when trying to close the application it crashes or it never finishes executing. This occurs when trying to release m_view in the destructor.

Source code: https://github.com/ZeroPass/NoesisGui-Qt-Binding
NoesisGui SDK version: 1.3.0b4
Render device: GLRenderDevice (provided by sdk)
Note: Binding works correctly with Noesis v1.2
Last edited by Keyboarder on 30 Jan 2017, 12:19, edited 1 time in total.
 
User avatar
jsantos
Site Admin
Posts: 3905
Joined: 20 Jan 2012, 17:18
Contact:

Re: Qt binding

20 Jan 2017, 08:33

What kind of crash are you getting? (Access violation?) Have you installed an error handler?

Apart from the CPU usage, how is the GPU, the number of FPS is the same to 1.2 or worse?
 
Keyboarder
Topic Author
Posts: 21
Joined: 21 Oct 2014, 11:57

Re: Qt binding

20 Jan 2017, 12:06

I've just realized that the crash happens if I remove m_view.Reset() from destructor. If I put it back the application never exits and continues to run with high CPU usage. The FPS count is slightly lower in 1.3 then in previous version (about 0.3 fps).
 
User avatar
jsantos
Site Admin
Posts: 3905
Joined: 20 Jan 2012, 17:18
Contact:

Re: Qt binding

20 Jan 2017, 19:47

You have to reset the view at destructor time. That's mandatory. What do you mean with "application never exits" ? You mean that the Reset() function never returns?

Did you install an error handler?

Are you rendering with vsync activated? If it is off, that could explain the high CPU usage.
 
Keyboarder
Topic Author
Posts: 21
Joined: 21 Oct 2014, 11:57

Re: Qt binding

22 Jan 2017, 16:18

That is correct, the Reset() method never returns when calling it from the destructor. I've initialized error handle, but it does not log anything.
Are you rendering with vsync activated? If it is off, that could explain the high CPU usage.
I have vsync activated, I think the problem with high CPU usage has to do something with how Qt handles rendering. Usually it is within main thread. I've already tried to find the way around this. One solution was putting renderer->Render() on separate thread but it didn't work.
 
Keyboarder
Topic Author
Posts: 21
Joined: 21 Oct 2014, 11:57

Re: Qt binding

23 Jan 2017, 11:04

Just a quick update... I've made device and context as a mamber variable and try to reset them prior to the m_view.Reset(). It looks like the problem is within context.Reset() because it never finish executing.
QNoesisWindow::~QNoesisWindow() 
{
    m_deviceReset();     // Ok
    m_context.Reset();   // Error: Does not return
    m_view.Reset();
}
 
User avatar
jsantos
Site Admin
Posts: 3905
Joined: 20 Jan 2012, 17:18
Contact:

Re: Qt binding

23 Jan 2017, 20:14

Ok, let's move this to a ticket in the tracker please. I am going to need dumps and more specific details about the project.

Thanks!
 
Keyboarder
Topic Author
Posts: 21
Joined: 21 Oct 2014, 11:57

Re: Qt binding

30 Jan 2017, 12:17

Finally, I've made some progress. I was able to put render process on a different thread. Cpu usage is significantly lower and app closes normally now. However, there are still some issues. For more info please visit provided url link to the ful source code.

There is still problem with resetting IView/VGContext Ptr when more than one noesis widget (QNoesisWidget) objects is created. The First object is destroyed normally, in any other object the execution is stalled in destructor when IView Ptr is being destroyed. On macOS, the app would crash with an error: "glDeleteSamplers(1, &sampler) [GL_INVALID_OPERATION]". This was solved by deleting IView before VGContext. However on windows it infinetly loops at:

void GLRenderDevice::DeleteTexture(GLuint texture) const
{
NS_ASSERT(glIsTexture(texture));
V(glDeleteTextures(1, &texture));
}

I figured it out that this line: while(glGetError() != GL_NO_ERROR); in macro V could be the problem. glGetError() always returns GL_INVALID_OPERATION (0x502). I did not find what the cause for gl error was.

The second issue that i have are random Cpu spikes when app is idle (app is active but no animation is being rendered). It can consume up to 60% cpu even thou the render process is being executed on a separate thread. In normal state it consumes ~8% Cpu. I don't know what the cause is either Qt or IView Renderer. Anyhow it helps if i limit fps count to ~35.


Full source code: https://github.com/ZeroPass/NoesisGui-Qt-Binding
Note: there is also a flickering issue when resizing widget but i think this problem is with how QWidget handles resize event.
 
User avatar
jsantos
Site Admin
Posts: 3905
Joined: 20 Jan 2012, 17:18
Contact:

Re: Qt binding

01 Feb 2017, 19:30

I figured it out that this line: while(glGetError() != GL_NO_ERROR); in macro V could be the problem. glGetError() always returns GL_INVALID_OPERATION (0x502). I did not find what the cause for gl error was.
is there an active GL context at that point? (just check with wglGetCurrentContext). Also make sure to create just one pair of RenderDevice + VGContext for all your views. Make also sure to do the renderer Init() and Shutdown() once in the render thread.

I have been fixing a few things for the next version. Right now, the View must be destroyed after the VGContext. This implied a synchronization between main and render thread. I eliminated that annoying constraint.
The second issue that i have are random Cpu spikes when app is idle (app is active but no animation is being rendered). It can consume up to 60% cpu even thou the render process is being executed on a separate thread. In normal state it consumes ~8% Cpu. I don't know what the cause is either Qt or IView Renderer. Anyhow it helps if i limit fps count to ~35.
Could you use Very Sleepy or even Visual Studio to analyze what's going on in those spikes?

Thanks!
 
Keyboarder
Topic Author
Posts: 21
Joined: 21 Oct 2014, 11:57

Re: Qt binding

19 Feb 2017, 23:03

is there an active GL context at that point? (just check with wglGetCurrentContext). Also make sure to create just one pair of RenderDevice + VGContext for all your views. Make also sure to do the renderer Init() and Shutdown() once in the render thread.

I have been fixing a few things for the next version. Right now, the View must be destroyed after the VGContext. This implied a synchronization between main and render thread. I eliminated that annoying constraint.
The wglGetCurrentContext returns 0x0, so I guess there shouldn't be any active context at this point. Also Init() and Shutdown() are invoked only once per app run.
The second issue that i have are random Cpu spikes when app is idle (app is active but no animation is being rendered). It can consume up to 60% cpu even thou the render process is being executed on a separate thread. In normal state it consumes ~8% Cpu. I don't know what the cause is either Qt or IView Renderer. Anyhow it helps if i limit fps count to ~35.
Could you use Very Sleepy or even Visual Studio to analyze what's going on in those spikes?
With Visual Studio's performance profiler I couldn't determine what exactly causes the cpu spikes but I did see that 50% of cpu is used by nvoglv32.dll, which i guess is nvidia's implementation of opengl. The other 1/3 is used by qt trying to make context current (wglMakeCurrent). I would assume that this is not then noesis fault but rather qt's or nvidia's. For reference, I've made QNoesisWindow class where renderer runs on the main thread. In this case, the majority of CPU is consumed by Noesis::Render::GLRenderDevice::MapBufferRange since it runs on a single thread but have no problems with nvoglv32.

Since Qt is event driven framework would it be possible to connect IView to some render pending / animation begin event, so I could run the render loop only when needed and stop when UI is steady? In this case I could run noesis renderer on single thread and I think it would solve all current problems including CPU usage and screen flickering when resizing. Just for info Qt handles animations this way.

Who is online

Users browsing this forum: Google [Bot] and 86 guests