TestParallelRendering.cxx 5.17 KB
Newer Older
1
2
3
/*=========================================================================

  Program:   Visualization Toolkit
4
  Module:    TestParallelRendering.cxx
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include <mpi.h>

#include "vtkMPICommunicator.h"
#include "vtkMPIController.h"
#include "vtkSynchronizedRenderWindows.h"
21
#include "vtkCompositedSynchronizedRenderers.h"
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include "vtkTestUtilities.h"
#include "vtkRegressionTestImage.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkOpenGLRenderWindow.h"
#include "vtkRenderer.h"
#include "vtkActor.h"
#include "vtkSphereSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkLookupTable.h"
#include "vtkCamera.h"
#include "vtkPieceScalars.h"
#include "vtkProcess.h"
#include "vtkObjectFactory.h"

Ben Boeckel's avatar
Ben Boeckel committed
36
37
38
namespace
{

39
40
41
42
class MyProcess : public vtkProcess
{
public:
  static MyProcess *New();
43

44
45
46
47
48
49
  virtual void Execute();

  void SetArgs(int anArgc,
               char *anArgv[])
    {
      this->Argc=anArgc;
50
      this->Argv=anArgv;
51
52
53
54
55
56
57
58
59
60
    }

  void CreatePipeline(vtkRenderer* renderer)
    {
    int num_procs = this->Controller->GetNumberOfProcesses();
    int my_id = this->Controller->GetLocalProcessId();

    vtkSphereSource* sphere = vtkSphereSource::New();
    sphere->SetPhiResolution(100);
    sphere->SetThetaResolution(100);
61

62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
    vtkPieceScalars *piecescalars = vtkPieceScalars::New();
    piecescalars->SetInputConnection(sphere->GetOutputPort());
    piecescalars->SetScalarModeToCellData();

    vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();
    mapper->SetInputConnection(piecescalars->GetOutputPort());
    mapper->SetScalarModeToUseCellFieldData();
    mapper->SelectColorArray("Piece");
    mapper->SetScalarRange(0, num_procs-1);
    mapper->SetPiece(my_id);
    mapper->SetNumberOfPieces(num_procs);
    mapper->Update();

    vtkActor* actor = vtkActor::New();
    actor->SetMapper(mapper);
    renderer->AddActor(actor);

    actor->Delete();
    mapper->Delete();
    piecescalars->Delete();
    sphere->Delete();
    }
84

85
86
protected:
  MyProcess() { this->Argc = 0; this->Argv = NULL; }
87

88
89
90
91
92
93
94
95
  int Argc;
  char **Argv;
};

vtkStandardNewMacro(MyProcess);

void MyProcess::Execute()
{
Dave DeMarle's avatar
Dave DeMarle committed
96
  this->ReturnValue = 0;
97
  int my_id = this->Controller->GetLocalProcessId();
98
  int numProcs = this->Controller->GetNumberOfProcesses();
99
100
101
102
103
104
105
106
107
108
109
110
111

  vtkRenderWindow* renWin = vtkRenderWindow::New();
  renWin->DoubleBufferOn();
  vtkRenderer* renderer = vtkRenderer::New();

  renWin->AddRenderer(renderer);

  vtkSynchronizedRenderWindows* syncWindows =
    vtkSynchronizedRenderWindows::New();
  syncWindows->SetRenderWindow(renWin);
  syncWindows->SetParallelController(this->Controller);
  syncWindows->SetIdentifier(1);

112
113
  vtkCompositedSynchronizedRenderers* syncRenderers =
    vtkCompositedSynchronizedRenderers::New();
114
115
  syncRenderers->SetRenderer(renderer);
  syncRenderers->SetParallelController(this->Controller);
116
  //syncRenderers->SetImageReductionFactor(3);
117
118
119

  this->CreatePipeline(renderer);

120
121
  int retVal;

122
123
124
125
  if (my_id == 0)
    {
    vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::New();
    iren->SetRenderWindow(renWin);
126
127
128
129
130
131
132
133
    iren->Initialize();

    retVal = vtkRegressionTester::Test(this->Argc, this->Argv, renWin, 10);

    if ( retVal == vtkRegressionTester::DO_INTERACTOR)
      {
      iren->Start();
      }
134
135
136
    iren->Delete();

    this->Controller->TriggerBreakRMIs();
137
138
139
140
141
    // This should really be Broadcast
    for (int i = 1; i < numProcs; i++)
      {
      this->Controller->Send(&retVal, 1, i, 33);
      }
142
143
144
145
    }
  else
    {
    this->Controller->ProcessRMIs();
146
    this->Controller->Receive(&retVal, 1, 0, 33);
147
148
149
150
151
152
    }

  renderer->Delete();
  renWin->Delete();
  syncWindows->Delete();
  syncRenderers->Delete();
153
  this->ReturnValue = retVal;
154
155
}

Ben Boeckel's avatar
Ben Boeckel committed
156
}
157

Ben Boeckel's avatar
Ben Boeckel committed
158
int TestParallelRendering(int argc, char *argv[])
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
{
  // This is here to avoid false leak messages from vtkDebugLeaks when
  // using mpich. It appears that the root process which spawns all the
  // main processes waits in MPI_Init() and calls exit() when
  // the others are done, causing apparent memory leaks for any objects
  // created before MPI_Init().
  MPI_Init(&argc, &argv);

  // Note that this will create a vtkMPIController if MPI
  // is configured, vtkThreadedController otherwise.
  vtkMPIController *contr = vtkMPIController::New();
  contr->Initialize(&argc, &argv, 1);

  int retVal = 1; //1==failed


  int numProcs = contr->GetNumberOfProcesses();

  if (numProcs < 2 && false)
    {
    cout << "This test requires at least 2 processes" << endl;
    contr->Delete();
    return retVal;
    }

  vtkMultiProcessController::SetGlobalController(contr);

  MyProcess *p=MyProcess::New();
  p->SetArgs(argc,argv);
188

189
190
  contr->SetSingleProcessObject(p);
  contr->SingleMethodExecute();
191

192
193
194
195
196
197
  retVal=p->GetReturnValue();

  p->Delete();
  contr->Finalize();
  contr->Delete();
  vtkMultiProcessController::SetGlobalController(0);
198
  return !retVal;
199
}