Commit dd3801a1 authored by Ken Martin's avatar Ken Martin
Browse files

Fix a few issues with parallel passes in VTK

Fixes a number of runtime failures in OpenGL2 with these
parallel passes.  Added a simple test to verify the code runs.

Change-Id: I2bcd998ab013412f7ee89c5ee122e9a1108954c6
parent 6db025c8
......@@ -15,7 +15,7 @@ set(Module_SRCS
vtkImageRenderManager.cxx
)
set(shader_files vtkCompositeZPassShader_fs.glsl)
set(shader_files vtkCompositeZPassShader_fs.glsl vtkCompositeZPassFS.glsl)
unset(shader_h_files)
foreach(file ${shader_files})
......
......@@ -16,6 +16,7 @@ vtk_test_cxx_executable(${vtk-module}CxxTests tests)
vtk_add_test_mpi(${vtk-module}CxxTests-MPI tests
RENDERING_DATA
TestSimplePCompositeZPass.cxx
${extra_opengl_tests}
)
vtk_add_test_mpi(${vtk-module}CxxTests-MPI no_data_tests
......
/*=========================================================================
Program: Visualization Toolkit
Module: TestPCompositeZPass.cxx
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.
=========================================================================*/
// The scene consists of
// * 4 actors: a rectangle, a box, a cone and a sphere. The box, the cone and
// the sphere are above the rectangle.
// * 2 spotlights: one in the direction of the box, another one in the
// direction of the sphere. Both lights are above the box, the cone and
// the sphere.
//
// The command line arguments are:
// -I => run in interactive mode; unless this is used, the program will
// not allow interaction and exit
#include "vtkObjectFactory.h"
#include <mpi.h>
#include "vtkMPICommunicator.h"
#include "vtkMPIController.h"
#include "vtkCompositeRenderManager.h"
#include "vtkTestUtilities.h"
#include "vtkRegressionTestImage.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkOpenGLRenderWindow.h"
#include "vtkOpenGLRenderer.h"
#include "vtkActor.h"
#include "vtkImageSinusoidSource.h"
#include "vtkImageData.h"
#include "vtkImageDataGeometryFilter.h"
#include "vtkDataSetSurfaceFilter.h"
#include "vtkPolyDataMapper.h"
#include "vtkLookupTable.h"
#include "vtkCamera.h"
#include "vtkCameraPass.h"
#include "vtkLightsPass.h"
#include "vtkSequencePass.h"
#include "vtkOpaquePass.h"
#include "vtkDepthPeelingPass.h"
#include "vtkTranslucentPass.h"
#include "vtkVolumetricPass.h"
#include "vtkOverlayPass.h"
#include "vtkRenderPassCollection.h"
#include "vtkCompositeZPass.h"
#include "vtkConeSource.h"
#include "vtkPlaneSource.h"
#include "vtkCubeSource.h"
#include "vtkSphereSource.h"
#include "vtkInformation.h"
#include "vtkProperty.h"
#include "vtkLight.h"
#include "vtkLightCollection.h"
#include <cassert>
#include "vtkMath.h"
#include "vtkFrustumSource.h"
#include "vtkPlanes.h"
#include "vtkActorCollection.h"
#include "vtkPolyDataNormals.h"
#include "vtkPointData.h"
#include "vtkLightActor.h"
#include "vtkProcess.h"
#include "vtkImageImport.h"
#include "vtkImageShiftScale.h"
#include "vtkImageAppendComponents.h"
#include "vtkSmartPointer.h"
#define VTK_CREATE(type, name) \
vtkSmartPointer<type> name = vtkSmartPointer<type>::New()
namespace
{
// Defined in TestLightActor.cxx
// For each spotlight, add a light frustum wireframe representation and a cone
// wireframe representation, colored with the light color.
void AddLightActors(vtkRenderer *r);
class MyProcess : public vtkProcess
{
public:
static MyProcess *New();
vtkTypeMacro(MyProcess, vtkProcess);
virtual void Execute();
void SetArgs(int anArgc,
char *anArgv[])
{
this->Argc=anArgc;
this->Argv=anArgv;
}
protected:
MyProcess();
int Argc;
char **Argv;
};
vtkStandardNewMacro(MyProcess);
MyProcess::MyProcess()
{
this->Argc=0;
this->Argv=0;
}
void MyProcess::Execute()
{
// multiprocesss logic
int numProcs=this->Controller->GetNumberOfProcesses();
int me=this->Controller->GetLocalProcessId();
vtkCompositeRenderManager *prm = vtkCompositeRenderManager::New();
vtkRenderWindowInteractor *iren=0;
if(me==0)
{
iren=vtkRenderWindowInteractor::New();
}
vtkRenderWindow *renWin = prm->MakeRenderWindow();
renWin->SetMultiSamples(0);
renWin->SetAlphaBitPlanes(1);
if(me==0)
{
iren->SetRenderWindow(renWin);
}
vtkRenderer *renderer = prm->MakeRenderer();
renWin->AddRenderer(renderer);
renderer->Delete();
vtkCameraPass *cameraP=vtkCameraPass::New();
vtkOpaquePass *opaque=vtkOpaquePass::New();
vtkLightsPass *lights=vtkLightsPass::New();
vtkCompositeZPass *compositeZPass=vtkCompositeZPass::New();
compositeZPass->SetController(this->Controller);
vtkSequencePass *seq=vtkSequencePass::New();
vtkRenderPassCollection *passes=vtkRenderPassCollection::New();
passes->AddItem(lights);
passes->AddItem(opaque);
passes->AddItem(compositeZPass);
compositeZPass->Delete();
seq->SetPasses(passes);
cameraP->SetDelegatePass(seq);
vtkOpenGLRenderer *glrenderer = vtkOpenGLRenderer::SafeDownCast(renderer);
glrenderer->SetPass(cameraP);
vtkPlaneSource *rectangleSource=vtkPlaneSource::New();
rectangleSource->SetOrigin(-5.0,0.0,5.0);
rectangleSource->SetPoint1(5.0,0.0,5.0);
rectangleSource->SetPoint2(-5.0,0.0,-5.0);
rectangleSource->SetResolution(100,100);
vtkPolyDataMapper *rectangleMapper=vtkPolyDataMapper::New();
rectangleMapper->SetInputConnection(rectangleSource->GetOutputPort());
rectangleSource->Delete();
rectangleMapper->SetScalarVisibility(0);
vtkActor *rectangleActor=vtkActor::New();
rectangleActor->SetMapper(rectangleMapper);
rectangleMapper->Delete();
rectangleActor->SetVisibility(1);
rectangleActor->GetProperty()->SetColor(1.0,1.0,1.0);
vtkCubeSource *boxSource=vtkCubeSource::New();
boxSource->SetXLength(2.0);
vtkPolyDataNormals *boxNormals=vtkPolyDataNormals::New();
boxNormals->SetInputConnection(boxSource->GetOutputPort());
boxNormals->SetComputePointNormals(0);
boxNormals->SetComputeCellNormals(1);
boxNormals->Update();
boxNormals->GetOutput()->GetPointData()->SetNormals(0);
vtkPolyDataMapper *boxMapper=vtkPolyDataMapper::New();
boxMapper->SetInputConnection(boxNormals->GetOutputPort());
boxNormals->Delete();
boxSource->Delete();
boxMapper->SetScalarVisibility(0);
vtkActor *boxActor=vtkActor::New();
boxActor->SetMapper(boxMapper);
boxMapper->Delete();
boxActor->SetVisibility(1);
boxActor->SetPosition(-2.0,2.0,0.0);
boxActor->GetProperty()->SetColor(1.0,0.0,0.0);
vtkConeSource *coneSource=vtkConeSource::New();
coneSource->SetResolution(24);
coneSource->SetDirection(1.0,1.0,1.0);
vtkPolyDataMapper *coneMapper=vtkPolyDataMapper::New();
coneMapper->SetInputConnection(coneSource->GetOutputPort());
coneSource->Delete();
coneMapper->SetScalarVisibility(0);
vtkActor *coneActor=vtkActor::New();
coneActor->SetMapper(coneMapper);
coneMapper->Delete();
coneActor->SetVisibility(1);
coneActor->SetPosition(0.0,1.0,1.0);
coneActor->GetProperty()->SetColor(0.0,0.0,1.0);
// coneActor->GetProperty()->SetLighting(false);
vtkSphereSource *sphereSource=vtkSphereSource::New();
sphereSource->SetThetaResolution(32);
sphereSource->SetPhiResolution(32);
vtkPolyDataMapper *sphereMapper=vtkPolyDataMapper::New();
sphereMapper->SetInputConnection(sphereSource->GetOutputPort());
sphereSource->Delete();
sphereMapper->SetScalarVisibility(0);
vtkActor *sphereActor=vtkActor::New();
sphereActor->SetMapper(sphereMapper);
sphereMapper->Delete();
sphereActor->SetVisibility(1);
sphereActor->SetPosition(2.0,2.0,-1.0);
sphereActor->GetProperty()->SetColor(1.0,1.0,0.0);
renderer->AddViewProp(rectangleActor);
rectangleActor->Delete();
renderer->AddViewProp(boxActor);
boxActor->Delete();
renderer->AddViewProp(coneActor);
coneActor->Delete();
renderer->AddViewProp(sphereActor);
sphereActor->Delete();
// Spotlights.
// lighting the box.
vtkLight *l1=vtkLight::New();
l1->SetPosition(-4.0,4.0,-1.0);
l1->SetFocalPoint(boxActor->GetPosition());
l1->SetColor(1.0,1.0,1.0);
l1->SetPositional(1);
renderer->AddLight(l1);
l1->SetSwitch(1);
l1->Delete();
// lighting the sphere
vtkLight *l2=vtkLight::New();
l2->SetPosition(4.0,5.0,1.0);
l2->SetFocalPoint(sphereActor->GetPosition());
l2->SetColor(1.0,0.0,1.0);
// l2->SetColor(1.0,1.0,1.0);
l2->SetPositional(1);
renderer->AddLight(l2);
l2->SetSwitch(1);
l2->Delete();
AddLightActors(renderer);
renderer->SetBackground(0.66,0.66,0.66);
renderer->SetBackground2(157.0/255.0*0.66,186/255.0*0.66,192.0/255.0*0.66);
renderer->SetGradientBackground(true);
renWin->SetSize(400,400); // 400,400
renWin->SetPosition(0, 460*me); // translate the window
prm->SetRenderWindow(renWin);
prm->SetController(this->Controller);
if(me==0)
{
rectangleActor->SetVisibility(false);
boxActor->SetVisibility(false);
}
else
{
coneActor->SetVisibility(false);
sphereActor->SetVisibility(false);
}
int retVal;
const int MY_RETURN_VALUE_MESSAGE=0x518113;
if(me>0)
{
// satellite nodes
prm->StartServices(); // start listening other processes (blocking call).
// receive return value from root process.
this->Controller->Receive(&retVal, 1, 0, MY_RETURN_VALUE_MESSAGE);
}
else
{
// root node
renWin->Render();
vtkCamera *camera=renderer->GetActiveCamera();
camera->Azimuth(40.0);
camera->Elevation(10.0);
renderer->ResetCamera();
// testing code
double thresh=10;
int i;
VTK_CREATE(vtkTesting, testing);
for (i = 0; i < this->Argc; ++i)
{
testing->AddArgument(this->Argv[i]);
}
if (testing->IsInteractiveModeSpecified())
{
retVal=vtkTesting::DO_INTERACTOR;
}
else
{
testing->FrontBufferOff();
for (i=0; i<this->Argc; i++)
{
if ( strcmp("-FrontBuffer", this->Argv[i]) == 0 )
{
testing->FrontBufferOn();
}
}
if (testing->IsValidImageSpecified())
{
renWin->Render();
if(compositeZPass->IsSupported(
static_cast<vtkOpenGLRenderWindow *>(renWin)))
{
int *dims;
dims=renWin->GetSize();
float *zBuffer=new float[dims[0]*dims[1]];
renWin->GetZbufferData(0,0,dims[0]-1,dims[1]-1,zBuffer);
vtkImageImport *importer=vtkImageImport::New();
size_t byteSize=static_cast<size_t>(dims[0]*dims[1]);
byteSize=byteSize*sizeof(float);
importer->CopyImportVoidPointer(zBuffer,static_cast<int>(byteSize));
importer->SetDataScalarTypeToFloat();
importer->SetNumberOfScalarComponents(1);
importer->SetWholeExtent(0,dims[0]-1,0,dims[1]-1,0,0);
importer->SetDataExtentToWholeExtent();
vtkImageShiftScale *converter=vtkImageShiftScale::New();
converter->SetInputConnection(importer->GetOutputPort());
converter->SetOutputScalarTypeToUnsignedChar();
converter->SetShift(0.0);
converter->SetScale(255.0);
// vtkImageDifference requires 3 components.
vtkImageAppendComponents *luminanceToRGB=
vtkImageAppendComponents::New();
luminanceToRGB->SetInputConnection(0,converter->GetOutputPort());
luminanceToRGB->AddInputConnection(0,converter->GetOutputPort());
luminanceToRGB->AddInputConnection(0,converter->GetOutputPort());
luminanceToRGB->Update();
retVal=testing->RegressionTest(luminanceToRGB,thresh);
luminanceToRGB->Delete();
converter->Delete();
importer->Delete();
delete[] zBuffer;
}
else
{
retVal=vtkTesting::PASSED; // not supported.
}
}
else
{
retVal=vtkTesting::NOT_RUN;
}
}
if(retVal==vtkRegressionTester::DO_INTERACTOR)
{
iren->Start();
}
prm->StopServices(); // tells satellites to stop listening.
// send the return value to the satellites
i=1;
while(i<numProcs)
{
this->Controller->Send(&retVal, 1, i, MY_RETURN_VALUE_MESSAGE);
++i;
}
iren->Delete();
}
renWin->Delete();
opaque->Delete();
seq->Delete();
passes->Delete();
cameraP->Delete();
lights->Delete();
prm->Delete();
this->ReturnValue=retVal;
}
// DUPLICATE for VTK/Rendering/Testing/Cxx/TestLightActor.cxx
// For each spotlight, add a light frustum wireframe representation and a cone
// wireframe representation, colored with the light color.
void AddLightActors(vtkRenderer *r)
{
assert("pre: r_exists" && r!=0);
vtkLightCollection *lights=r->GetLights();
lights->InitTraversal();
vtkLight *l=lights->GetNextItem();
while(l!=0)
{
double angle=l->GetConeAngle();
if(l->LightTypeIsSceneLight() && l->GetPositional()
&& angle<180.0) // spotlight
{
vtkLightActor *la=vtkLightActor::New();
la->SetLight(l);
r->AddViewProp(la);
la->Delete();
}
l=lights->GetNextItem();
}
}
}
int TestSimplePCompositeZPass(int argc, char *argv[])
{
// 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
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;
}
MyProcess *p=MyProcess::New();
p->SetArgs(argc,argv);
contr->SetSingleProcessObject(p);
contr->SingleMethodExecute();
retVal=p->GetReturnValue();
p->Delete();
contr->Finalize();
contr->Delete();
return !retVal;
}
......@@ -231,6 +231,8 @@ void vtkCompositeRGBAPass::Render(const vtkRenderState *s)
this->RawRGBABuffer=new float[this->RawRGBABufferSize];
}
//size_t byteSize = this->RawRGBABufferSize*sizeof(unsigned char);
if(this->PBO==0)
{
this->PBO=vtkPixelBufferObject::New();
......@@ -371,14 +373,13 @@ void vtkCompositeRGBAPass::Render(const vtkRenderState *s)
#else
vtkgl::BlendFuncSeparate(GL_ONE,GL_ONE_MINUS_SRC_ALPHA,
GL_ONE,GL_ONE_MINUS_SRC_ALPHA);
#endif
// fixed vertex shader
glDisable(GL_LIGHTING);
// fixed fragment shader
glEnable(GL_TEXTURE_2D);
glDisable(GL_FOG);
#endif
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
glPixelStorei(GL_UNPACK_ALIGNMENT,1);// client to server
......@@ -435,18 +436,15 @@ void vtkCompositeRGBAPass::Render(const vtkRenderState *s)
}
#ifdef VTKGL2
to->Activate();
to->CopyToFrameBuffer(0, 0, w - 1, h - 1, 0, 0, w, h, NULL, NULL);
to->Deactivate();
#else
vtkgl::ActiveTexture(vtkgl::TEXTURE0);
#endif
// fixed-pipeline for vertex and fragment shaders.
to->Bind();
#ifdef VTKGL2
to->CopyToFrameBuffer(0, 0, w - 1, h - 1, 0, 0, w, h, NULL, NULL);
to->Deactivate();
#else
to->CopyToFrameBuffer(0,0,w-1,h-1,0,0,w,h);
#endif
to->UnBind();
#endif
--procIndex;
}
glPopAttrib();
......
......@@ -21,7 +21,6 @@
#include "vtkFrameBufferObject.h"
#include "vtkTextureObject.h"
#include "vtkOpenGLRenderWindow.h"
#include "vtkTextureUnitManager.h"
// to be able to dump intermediate result into png files for debugging.
// only for vtkCompositeZPass developers.
......@@ -51,19 +50,20 @@
# include "vtkShaderProgram.h"
# include "vtkglVBOHelper.h"
# include "vtkTextureObjectVS.h"
# include "vtkCompositeZPassFS.h"
#else
# include "vtkgl.h"
# include "vtkShaderProgram2.h"
# include "vtkShader2.h"
# include "vtkShader2Collection.h"
# include "vtkTextureUnitManager.h"
# include "vtkUniformVariables.h"
extern const char *vtkCompositeZPassShader_fs;
#endif
vtkStandardNewMacro(vtkCompositeZPass);
vtkCxxSetObjectMacro(vtkCompositeZPass,Controller,vtkMultiProcessController);
extern const char *vtkCompositeZPassShader_fs;
// ----------------------------------------------------------------------------
vtkCompositeZPass::vtkCompositeZPass()
{
......@@ -462,9 +462,6 @@ void vtkCompositeZPass::Render(const vtkRenderState *s)