realwhzc
(ZZ)
December 6, 2023, 1:54am
1
I replaced
int DistributedDataRenderPass(int argc, char* argv )
by
int main(int argc, char* argv )
I used mpiexec to run it ,but the rendering window flashed by.
I added cin.get() after iren->start() to make the render window hover, But the render window cannot interact.
How to use parallel rendering correctly in VTK?
realwhzc
(ZZ)
December 11, 2023, 3:07am
2
// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
// SPDX-License-Identifier: BSD-3-Clause
// Test of vtkDistributedDataFilter and supporting classes, covering as much
// code as possible. This test requires 4 MPI processes.
//
// To cover ghost cell creation, use vtkDataSetSurfaceFilter.
//
// To cover clipping code: SetBoundaryModeToSplitBoundaryCells()
//
// To run fast redistribution: SetUseMinimalMemoryOff() (Default)
// To run memory conserving code instead: SetUseMinimalMemoryOn()
#include "vtkActor.h"
#include "vtkCamera.h"
#include "vtkCameraPass.h"
#include "vtkClearZPass.h"
#include "vtkCompositeRGBAPass.h"
#include "vtkCompositeRenderManager.h"
#include "vtkDataSetReader.h"
#include "vtkDataSetSurfaceFilter.h"
#include "vtkDistributedDataFilter.h"
#include "vtkImageRenderManager.h"
#include "vtkLightsPass.h"
#include "vtkMPIController.h"
#include "vtkNew.h"
#include "vtkObjectFactory.h"
#include "vtkOpaquePass.h"
#include "vtkOpenGLRenderWindow.h"
#include "vtkOpenGLRenderer.h"
#include "vtkOverlayPass.h"
#include "vtkPieceScalars.h"
#include "vtkPolyDataMapper.h"
#include "vtkProperty.h"
#include "vtkRegressionTestImage.h"
#include "vtkRenderPassCollection.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSequencePass.h"
#include "vtkTestErrorObserver.h"
#include "vtkTestUtilities.h"
#include "vtkTranslucentPass.h"
#include "vtkUnstructuredGrid.h"
#include "vtkVolumetricPass.h"
/*
** This test only builds if MPI is in use
*/
#include "vtkMPICommunicator.h"
#include "vtkProcess.h"
namespace
{
class MyProcess : public vtkProcess
{
public:
static MyProcess* New();
void Execute() override;
void SetArgs(int anArgc, char* anArgv[]);
protected:
MyProcess();
int Argc;
char** Argv;
};
vtkStandardNewMacro(MyProcess);
MyProcess::MyProcess()
{
this->Argc = 0;
this->Argv = nullptr;
}
void MyProcess::SetArgs(int anArgc, char* anArgv[])
{
this->Argc = anArgc;
this->Argv = anArgv;
}
void MyProcess::Execute()
{
this->ReturnValue = 1;
int numProcs = this->Controller->GetNumberOfProcesses();
int me = this->Controller->GetLocalProcessId();
int i, go;
// vtkCompositeRenderManager *prm = vtkCompositeRenderManager::New();
// vtkParallelRenderManager *prm = vtkParallelRenderManager::New();
vtkImageRenderManager* prm = vtkImageRenderManager::New();
vtkRenderWindowInteractor* iren = nullptr;
if (me == 0)
{
iren = vtkRenderWindowInteractor::New();
}
// READER
vtkDataSetReader* dsr = vtkDataSetReader::New();
vtkUnstructuredGrid* ug = vtkUnstructuredGrid::New();
vtkDataSet* ds = nullptr;
if (me == 0)
{
char* fname =
vtkTestUtilities::ExpandDataFileName(this->Argc, this->Argv, "Data/tetraMesh.vtk");
dsr->SetFileName("tetraMesh.vtk");
ds = dsr->GetOutput();
dsr->Update();
delete[] fname;
go = 1;
if ((ds == nullptr) || (ds->GetNumberOfCells() == 0))
{
if (ds)
{
cout << "Failure: input file has no cells" << endl;
}
go = 0;
}
}
else
{
ds = static_cast<vtkDataSet*>(ug);
}
vtkMPICommunicator* comm = vtkMPICommunicator::SafeDownCast(this->Controller->GetCommunicator());
comm->Broadcast(&go, 1, 0);
if (!go)
{
dsr->Delete();
ug->Delete();
prm->Delete();
return;
}
// DATA DISTRIBUTION FILTER
vtkDistributedDataFilter* dd = vtkDistributedDataFilter::New();
dd->SetInputData(ds);
dd->SetController(this->Controller);
dd->SetBoundaryModeToSplitBoundaryCells(); // clipping
dd->UseMinimalMemoryOff();
// COLOR BY PROCESS NUMBER
vtkPieceScalars* ps = vtkPieceScalars::New();
ps->SetInputConnection(dd->GetOutputPort());
ps->SetScalarModeToCellData();
// MORE FILTERING - this will request ghost cells
vtkDataSetSurfaceFilter* dss = vtkDataSetSurfaceFilter::New();
dss->SetInputConnection(ps->GetOutputPort());
// COMPOSITE RENDER
vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();
mapper->SetInputConnection(dss->GetOutputPort());
mapper->SetColorModeToMapScalars();
mapper->SetScalarModeToUseCellFieldData();
mapper->SelectColorArray("Piece");
mapper->SetScalarRange(0, numProcs - 1);
vtkActor* actor = vtkActor::New();
actor->SetMapper(mapper);
vtkProperty* p = actor->GetProperty();
p->SetOpacity(0.3);
vtkRenderer* renderer = prm->MakeRenderer();
vtkOpenGLRenderer* glrenderer = vtkOpenGLRenderer::SafeDownCast(renderer);
#if 1
// the rendering passes
vtkCameraPass* cameraP = vtkCameraPass::New();
vtkSequencePass* seq = vtkSequencePass::New();
vtkOpaquePass* opaque = vtkOpaquePass::New();
// vtkDepthPeelingPass *peeling=vtkDepthPeelingPass::New();
// peeling->SetMaximumNumberOfPeels(200);
// peeling->SetOcclusionRatio(0.1);
vtkTranslucentPass* translucent = vtkTranslucentPass::New();
// peeling->SetTranslucentPass(translucent);
vtkVolumetricPass* volume = vtkVolumetricPass::New();
vtkOverlayPass* overlay = vtkOverlayPass::New();
vtkLightsPass* lights = vtkLightsPass::New();
vtkClearZPass* clearZ = vtkClearZPass::New();
clearZ->SetDepth(0.9);
vtkNew<vtkTest::ErrorObserver> errorObserver1;
vtkCompositeRGBAPass* compositeRGBAPass = vtkCompositeRGBAPass::New();
compositeRGBAPass->AddObserver(vtkCommand::ErrorEvent, errorObserver1);
compositeRGBAPass->SetController(this->Controller);
compositeRGBAPass->SetKdtree(dd->GetKdtree());
vtkRenderPassCollection* passes = vtkRenderPassCollection::New();
passes->AddItem(lights);
passes->AddItem(opaque);
// passes->AddItem(clearZ);
// passes->AddItem(peeling);
passes->AddItem(translucent);
passes->AddItem(volume);
passes->AddItem(overlay);
passes->AddItem(compositeRGBAPass);
seq->SetPasses(passes);
cameraP->SetDelegatePass(seq);
glrenderer->SetPass(cameraP);
opaque->Delete();
// peeling->Delete();
translucent->Delete();
volume->Delete();
overlay->Delete();
compositeRGBAPass->Delete();
seq->Delete();
passes->Delete();
cameraP->Delete();
lights->Delete();
clearZ->Delete();
#endif
renderer->AddActor(actor);
vtkRenderWindow* renWin = prm->MakeRenderWindow();
renWin->SetMultiSamples(0);
renWin->SetAlphaBitPlanes(1);
if (me == 0)
{
iren->SetRenderWindow(renWin);
}
renWin->AddRenderer(renderer);
renderer->SetBackground(0, 0, 0);
renWin->SetSize(300, 300);
renWin->SetPosition(0, 360 * me);
prm->SetRenderWindow(renWin);
prm->SetController(this->Controller);
prm->InitializeOffScreen(); // Mesa GL only
// We must update the whole pipeline here, otherwise node 0
// goes into GetActiveCamera which updates the pipeline, putting
// it into vtkDistributedDataFilter::Execute() which then hangs.
// If it executes here, dd will be up-to-date won't have to
// execute in GetActiveCamera.
mapper->SetPiece(me);
mapper->SetNumberOfPieces(numProcs);
mapper->Update();
const int MY_RETURN_VALUE_MESSAGE = 0x11;
if (me == 0)
{
renderer->ResetCamera();
vtkCamera* camera = renderer->GetActiveCamera();
// camera->UpdateViewport(renderer);
camera->ParallelProjectionOn();
camera->SetParallelScale(16);
if (compositeRGBAPass->IsSupported(static_cast<vtkOpenGLRenderWindow*>(renWin)))
{
renWin->Render();
this->ReturnValue = vtkRegressionTester::Test(this->Argc, this->Argv, renWin, 10);
}
else
{
std::string gotMsg(errorObserver1->GetErrorMessage());
std::string expectedMsg("Missing required OpenGL extensions");
if (gotMsg.find(expectedMsg) == std::string::npos)
{
std::cout << "ERROR: Error message does not contain \"" << expectedMsg << "\" got \n\""
<< gotMsg << std::endl;
this->ReturnValue = vtkTesting::FAILED;
}
else
{
std::cout << expectedMsg << std::endl;
}
this->ReturnValue = vtkTesting::PASSED; // not supported.
}
if (1)//this->ReturnValue == vtkRegressionTester::DO_INTERACTOR
{
iren->Initialize();
iren->Start();
}
prm->StopServices();
for (i = 1; i < numProcs; i++)
{
this->Controller->Send(&this->ReturnValue, 1, i, MY_RETURN_VALUE_MESSAGE);
}
}
else
{
prm->StartServices();
this->Controller->Receive(&this->ReturnValue, 1, 0, MY_RETURN_VALUE_MESSAGE);
}
//if(me==0)
//iren->Start();
//cin.get();
#if 0
if (this->ReturnValue == vtkTesting::PASSED)
{
// Now try using the memory conserving *Lean methods. The
// image produced should be identical
dd->UseMinimalMemoryOn();
mapper->SetPiece(me);
mapper->SetNumberOfPieces(numProcs);
mapper->Update();
if (me == 0)
{
renderer->ResetCamera();
vtkCamera* camera = renderer->GetActiveCamera();
camera->UpdateViewport(renderer);
camera->ParallelProjectionOn();
camera->SetParallelScale(16);
renWin->Render();
if (compositeRGBAPass->IsSupported(static_cast<vtkOpenGLRenderWindow*>(renWin)))
{
this->ReturnValue = vtkRegressionTester::Test(this->Argc, this->Argv, renWin, 10);
}
else
{
this->ReturnValue = vtkTesting::PASSED; // not supported.
}
for (i = 1; i < numProcs; i++)
{
this->Controller->Send(&this->ReturnValue, 1, i, MY_RETURN_VALUE_MESSAGE);
}
prm->StopServices();
}
else
{
prm->StartServices();
this->Controller->Receive(&this->ReturnValue, 1, 0, MY_RETURN_VALUE_MESSAGE);
}
}
if (me == 0)
{
iren->Delete();
}
// CLEAN UP
mapper->Delete();
actor->Delete();
renderer->Delete();
renWin->Delete();
dd->Delete();
dsr->Delete();
ug->Delete();
ps->Delete();
dss->Delete();
prm->Delete();
#endif
}
}
int main(int argc, char* argv[])
{
int retVal = 1;
vtkMPIController* contr = vtkMPIController::New();
contr->Initialize(&argc, &argv);
vtkMultiProcessController::SetGlobalController(contr);
int numProcs = contr->GetNumberOfProcesses();
int me = contr->GetLocalProcessId();
if (numProcs < 2)
{
if (me == 0)
{
cout << "DistributedData test requires 2 processes" << endl;
}
contr->Delete();
return retVal;
}
if (!contr->IsA("vtkMPIController"))
{
if (me == 0)
{
cout << "DistributedData test requires MPI" << endl;
}
contr->Delete();
return retVal; // is this the right error val? TODO
}
MyProcess* p = MyProcess::New();
p->SetArgs(argc, argv);
contr->SetSingleProcessObject(p);
contr->SingleMethodExecute();
//retVal = p->GetReturnValue();
//p->Delete();
//cin.get();
contr->Finalize();
contr->Delete();
return retVal;
}