0
votes

Recently I was working on a real time CPP program displaying volume rendering image and some other polygon geometry using VTK at the same time. In my code, 4 vtkRenderer objects are instantiated to contain diferent kinds of vtkProp objects in a way as:

auto renderer1 = vtkSmartPointer<vtkRenderer>::New();
auto renderer2 = vtkSmartPointer<vtkRenderer>::New();
auto renderer3 = vtkSmartPointer<vtkRenderer>::New();
auto renderer4 = vtkSmartPointer<vtkRenderer>::New();

auto vtkActor1 = vtkSmartPointer<vtkActor>::New();
auto vtkActor2 = vtkSmartPointer<vtkActor>::New();
auto vtkActor3 = vtkSmartPointer<vtkActor>::New();
auto vtkVolume4 = vtkSmartPointer<vtkVolume>::New();

renderer1->AddActor(vtkActor1);
renderer2->AddActor(vtkActor2);
renderer3->AddActor(vtkActor3);
renderer4->AddVolume(vtkVolume4);

auto window1 = vtkSmartPointer<vtkRenderWindow>::New();
auto window2 = vtkSmartPointer<vtkRenderWindow>::New();
auto window3 = vtkSmartPointer<vtkRenderWindow>::New();
auto window4 = vtkSmartPointer<vtkRenderWindow>::New();
window1->AddRenderer(renderer1);
window2->AddRenderer(renderer2);
window3->AddRenderer(renderer3);
window4->AddRenderer(renderer4);

4 timer of QTWidget are created to rendering these window as time goes on. It’s very disappointed that the speed of program in a work-station with a Intel CORE I9 CPU and 2 Nvidia GTX 1080 TI (in SlI mode) has nearly no difference with in a laptop contains a Intel CORE I5 and a Nvidia GeForce 940mx.... The rendering of window1 to window3 are in some degree blocked by the ray-casting calculation in window4. On the other hand, The blocking problem of window1 to window3 will be overcome once the window 4 for ray-casting rendering is disabled. To improve the speed of rendering and take the full advantages of the I9 CPU and double GTX 1080 TI. At this time 4 std::thread are used to try to render these different window at different thread in a way as:

auto thread1 = new std::thread([&]()
{
    while (1)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
        window1->Render();
    }
});
thread1->detach();
auto thread2 = new std::thread([&]()
{
    while (1)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
        window2->Render();
    }
});
thread2->detach();
auto thread3 = new std::thread([&]()
{
    while (1)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
        window3->Render();
    }
});
thread3->detach();
auto thread4 = new std::thread([&]()
{
    while (1)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
        window4->Render();
    }
});
thread4->detach();

In this way it seems that the blocking problem of window1 to window3 are disappeared. Unfortunately once the mouse action is applied into any window, vtk runtime error: “ERROR: In D:\vtk7\VTK-7.1.1\Rendering\OpenGL\vtkWin32OpenGLRenderWindow.cxx, line 278 vtkWin32OpenGLRenderWindow (000002663199C870): wglMakeCurrent failed in MakeCurrent(), error:” will be generated and the program will be crashed after a randomly time.

At this time I am confused at how to make different render window rendered safely at deferent CPU thread. An alternative solution I guess may be that the window4 ray-casting rendering is applied on one Nvidia GTX 1080 TI and the window1 to window3 (without ray-casting) rendering are all applied on another Nvidia GTX 1080 TI. Does VTK support the working mode I describe above? How to accomplish it?

1
Multihreading openGL calls is rarely a good idea, see e.g. this question stackoverflow.com/questions/11097170 or google "opengl multhreaded rendering" for more info. The GPU will make each rendering pass as fast as it can, but it can do just one at a time anyway - making parallel openGL calls won't make it do two passes at the same time, so you don't get any real parallelism -> you don't get any speed-up that way. All you get is an extra overhead from switching contexts (you are forcing the GPU to render into four different buffers) and one big race condition...tomj

1 Answers

0
votes

You can't interact with the VTK GUI classes, like vtkRenderWindow, from outside the main thread, the thread where the event dispatch happens. When you do that all kinds of errors happen.

Also, I have never seen any program where a HWND component is rendered using a GPU and the others using another and, as far as I know, the GPU avaliable for your program is set when it starts, like in those notebooks with two GPUs. The only way to do so, as far as I know would be using OpenCL and doing the raycasting in one GPU and the rendering in another GPU but there is no such volume renderer in VTK.