Commit 52c7392f authored by Utkarsh Ayachit's avatar Utkarsh Ayachit

Refactors AMR streaming framework.

This commit refactors AMR streaming framework and add support for a mechanism
for streaming composite datasets in general. To try out amr streaming, run all
executables with "--enable-streaming" flag and open an AMR Flash or Enzo dataset
and render as "AMR Blocks" or "Volume" (currently, only works in builtin mode,
but will be supported in other modes soon).

vtkAMROutlineRepresentation is a example class that demonstrates how a
representation can leverage the streaming capabailities provided by
vtkPVRenderView.

vtkPVRenderView adds support to two new passes: REQUEST_STREAMING_UPDATE() and
REQUEST_PROCESS_STREAMED_PIECE().  REQUEST_STREAMING_UPDATE() is a view pass in
which the representations can update their data pipelines to request a certain
"piece" of the data. REQUEST_PROCESS_STREAMED_PIECE() is called on
representations to handle a "piece" just received by the process. This
separation makes it possible for representations to be agnostic of where the
data is processed and where it is rendered. It's the reposibility of the view
(vtkPVDataDeliveryManager in particular) to deliver the data to the
rendering nodes.

vtkPVDataDeliveryManager doesn't currently support data delivery for streamed
pieces, however. That's on the TODO list.
parent b5ce7caa
......@@ -61,7 +61,7 @@ vtkPVOptions::vtkPVOptions()
this->TellVersion = 0;
this->AMRStreaming = 0;
this->EnableStreaming = 0;
this->UseCudaInterop = 0;
......@@ -298,11 +298,10 @@ void vtkPVOptions::Initialize()
"When specified, the python script is processed symmetrically on all processes.",
vtkPVOptions::PVBATCH);
this->AddBooleanArgument("--amr-streaming", "-amr",
&this->AMRStreaming,
"EXPERIMENTAL: When specified, AMR streaming for volume rendering is "
"enabled",
vtkPVOptions::PVCLIENT | vtkPVOptions::PVSERVER);
this->AddBooleanArgument("--enable-streaming", 0, &this->EnableStreaming,
"EXPERIMENTAL: When specified, view-based streaming is enabled for certain "
"views and representation types.",
vtkPVOptions::ALLPROCESS);
this->AddBooleanArgument("--use-cuda-interop", "-cudaiop",
&this->UseCudaInterop,
......@@ -379,16 +378,6 @@ int vtkPVOptions::PostProcess(int, const char* const*)
}
#endif //PARAVIEW_ALWAYS_SECURE_CONNECTION
if (this->AMRStreaming)
{
vtkErrorMacro("FIXME");
// vtkPVView::SetEnableStreaming(true);
}
else
{
// vtkPVView::SetEnableStreaming(false);
}
return 1;
}
......@@ -538,7 +527,8 @@ void vtkPVOptions::PrintSelf(ostream& os, vtkIndent indent)
os << indent << "SymmetricMPIMode: " << this->SymmetricMPIMode << endl;
os << indent << "ServerURL: "
<< (this->ServerURL? this->ServerURL : "(none)") << endl;
os << indent << "AMRStreaming:" << this->AMRStreaming << endl;
os << indent << "EnableStreaming:" <<
(this->EnableStreaming? "yes" : "no") << endl;
os << indent << "UseCudaInterop" << this->UseCudaInterop << std::endl;
}
......@@ -150,8 +150,9 @@ public:
vtkSetStringMacro(ParaViewDataName);
// Description:
// EXPERIMENTAL: When set, AMR streaming is enabled.
vtkGetMacro(AMRStreaming, int);
// Until streaming becomes mainstream, we enable streaming support by passing
// a command line argument to all processes.
vtkGetMacro(EnableStreaming, int);
// Description:
// When set, use cuda interop feature
......@@ -258,7 +259,7 @@ private:
vtkSetStringMacro(StereoType);
char* StereoType;
int AMRStreaming;
int EnableStreaming;
int UseCudaInterop;
......
......@@ -30,6 +30,9 @@
#==========================================================================
set (Module_SRCS
vtk3DWidgetRepresentation.cxx
vtkAMROutlineRepresentation.cxx
vtkAMRStreamingPriorityQueue.cxx
vtkAMRStreamingVolumeRepresentation.cxx
vtkAMRVolumeRepresentation.cxx
vtkCaveSynchronizedRenderers.cxx
vtkChartRepresentation.cxx
......
/*=========================================================================
Program: ParaView
Module: $RCSfile$
Copyright (c) Kitware, Inc.
All rights reserved.
See Copyright.txt or http://www.paraview.org/HTML/Copyright.html 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.
=========================================================================*/
// .NAME vtkAMROutlineRepresentation - a simple outline representation for AMR
// datasets that supports streaming.
// .SECTION Description
// vtkAMROutlineRepresentation is a simple representation for Overlapping-AMR
// datasets that with streaming capabilities. It demonstrates how a
// representation can exploit streaming capabilities provided by ParaView's
// Render View (vtkPVRenderView).
#ifndef __vtkAMROutlineRepresentation_h
#define __vtkAMROutlineRepresentation_h
#include "vtkPVDataRepresentation.h"
#include "vtkSmartPointer.h" // for smart pointer.
#include "vtkBoundingBox.h" // needed for vtkBoundingBox.
class vtkAMRStreamingPriorityQueue;
class vtkCompositePolyDataMapper2;
class vtkPVLODActor;
class VTKPVCLIENTSERVERCORERENDERING_EXPORT vtkAMROutlineRepresentation :
public vtkPVDataRepresentation
{
public:
static vtkAMROutlineRepresentation* New();
vtkTypeMacro(vtkAMROutlineRepresentation, vtkPVDataRepresentation);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// Overridden to handle various view passes.
virtual int ProcessViewRequest(vtkInformationRequestKey* request_type,
vtkInformation* inInfo, vtkInformation* outInfo);
// Description:
// Get/Set the visibility for this representation. When the visibility of
// representation of false, all view passes are ignored.
virtual void SetVisibility(bool val);
//BTX
protected:
vtkAMROutlineRepresentation();
~vtkAMROutlineRepresentation();
// Description:
// Adds the representation to the view. This is called from
// vtkView::AddRepresentation(). Subclasses should override this method.
// Returns true if the addition succeeds.
virtual bool AddToView(vtkView* view);
// Description:
// Removes the representation to the view. This is called from
// vtkView::RemoveRepresentation(). Subclasses should override this method.
// Returns true if the removal succeeds.
virtual bool RemoveFromView(vtkView* view);
// Description:
// Fill input port information.
int FillInputPortInformation(int port, vtkInformation* info);
// Description:
// Overridden to check if the input pipeline is streaming capable. This method
// should check if streaming is enabled i.e. vtkPVView::GetEnableStreaming()
// and the input pipeline provides necessary AMR meta-data.
virtual int RequestInformation(vtkInformation *rqst,
vtkInformationVector **inputVector,
vtkInformationVector *outputVector);
// Description:
// Setup the block request. During StreamingUpdate, this will request the
// blocks based on priorities determined by the vtkAMRStreamingPriorityQueue,
// otherwise it doesn't make any specific request. AMR sources can treat the
// absence of specific block request to mean various things. It's expected
// that read only the root block (or a few more) in that case.
virtual int RequestUpdateExtent(vtkInformation* request,
vtkInformationVector** inputVector,
vtkInformationVector* outputVector);
// Description:
// Generate the outline for the current input.
// When not in StreamingUpdate, this also initializes the priority queue since
// the input AMR may have totally changed, including its structure.
virtual int RequestData(vtkInformation *rqst,
vtkInformationVector **inputVector,
vtkInformationVector *outputVector);
// Description:
// Returns true when the input pipeline supports streaming. It is set in
// RequestInformation().
vtkGetMacro(StreamingCapablePipeline, bool);
// Description:
// Returns true when StreamingUpdate() is being processed.
vtkGetMacro(InStreamingUpdate, bool);
// Description:
// Returns true if this representation has a "next piece" that it streamed.
// This method will update the PriorityQueue using the view planes specified
// and then call Update() on the representation, making it reexecute and
// regenerate the outline for the next "piece" of data.
bool StreamingUpdate(const double view_planes[24]);
// Description:
// This is the data object generated processed by the most recent call to
// RequestData() while not streaming.
// This is non-empty only on the data-server nodes.
vtkSmartPointer<vtkDataObject> ProcessedData;
// Description:
// This is the data object generated processed by the most recent call to
// RequestData() while streaming.
// This is non-empty only on the data-server nodes.
vtkSmartPointer<vtkDataObject> ProcessedPiece;
// Description:
// This is a trivial producer we use to feed data to the rendering pipeline.
// This doesn't need to be a vtkTrivialProducer, we could have just saved the
// data object. However, currently vtkAlgorithm doesn't provide a simple way
// to connect input data object without modifying the algorithm. Once that's
// fixed, we can clean this up.
vtkSmartPointer<vtkTrivialProducer> RenderedDataProducer;
// Description:
// vtkAMRStreamingPriorityQueue is a helper class we used to compute the order
// in which to request blocks from the input pipeline. Implementations can
// come up with their own rules to decide the request order based on
// application and data type.
vtkSmartPointer<vtkAMRStreamingPriorityQueue> PriorityQueue;
// Description:
// Actor used to render the outlines in the view.
vtkSmartPointer<vtkCompositePolyDataMapper2> Mapper;
vtkSmartPointer<vtkPVLODActor> Actor;
// Description:
// Used to keep track of data bounds.
vtkBoundingBox DataBounds;
private:
vtkAMROutlineRepresentation(const vtkAMROutlineRepresentation&); // Not implemented
void operator=(const vtkAMROutlineRepresentation&); // Not implemented
// Description:
// This flag is set to true if the input pipeline is streaming capable in
// RequestInformation(). Note that in client-server mode, this is valid only
// on the data-server nodes since all other nodes don't have input pipelines
// connected, they cannot indicate if the pipeline supports streaming.
bool StreamingCapablePipeline;
// Description:
// This flag is used to indicate that the representation is being updated
// during the streaming pass. RequestData() can use this flag to reset
// internal datastructures when the input changes for non-streaming reasons
// and we need to clear our streaming buffers since the streamed data is no
// longer valid.
bool InStreamingUpdate;
// Description:
// This flag is used as a hack for the time being to determine when the
// RenderedDataProducer is supposed to be empty. This is needed since the
// mapper cannot have NULL input.
bool RenderedDataProducerIsEmpty;
//ETX
};
#endif
/*=========================================================================
Program: ParaView
Module: $RCSfile$
Copyright (c) Kitware, Inc.
All rights reserved.
See Copyright.txt or http://www.paraview.org/HTML/Copyright.html 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 "vtkAMRStreamingPriorityQueue.h"
#include "vtkAMRInformation.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
#include <queue>
#include <algorithm>
//*****************************************************************************
namespace
{
// this code is stolen from vtkFrustumCoverageCuller.
double vtkComputeScreenCoverage(const double planes[24],
const double bounds[6], double &distance)
{
distance = 0.0;
// a duff dataset like a polydata with no cells will have bad bounds
if (!vtkMath::AreBoundsInitialized(const_cast<double*>(bounds)))
{
return 0.0;
}
double screen_bounds[4];
double center[3];
center[0] = (bounds[0] + bounds[1]) / 2.0;
center[1] = (bounds[2] + bounds[3]) / 2.0;
center[2] = (bounds[4] + bounds[5]) / 2.0;
double radius = 0.5 * sqrt(
( bounds[1] - bounds[0] ) * ( bounds[1] - bounds[0] ) +
( bounds[3] - bounds[2] ) * ( bounds[3] - bounds[2] ) +
( bounds[5] - bounds[4] ) * ( bounds[5] - bounds[4] ) );
for (int i = 0; i < 6; i++ )
{
// Compute how far the center of the sphere is from this plane
double d = planes[i*4 + 0] * center[0] +
planes[i*4 + 1] * center[1] +
planes[i*4 + 2] * center[2] +
planes[i*4 + 3];
// If d < -radius the prop is not within the view frustum
if ( d < -radius )
{
return 0.0;
}
// The first four planes are the ones bounding the edges of the
// view plane (the last two are the near and far planes) The
// distance from the edge of the sphere to these planes is stored
// to compute coverage.
if ( i < 4 )
{
screen_bounds[i] = d - radius;
}
// The fifth plane is the near plane - use the distance to
// the center (d) as the value to sort by
if ( i == 4 )
{
distance = d;
}
}
// If the prop wasn't culled during the plane tests...
// Compute the width and height of this slice through the
// view frustum that contains the center of the sphere
double full_w = screen_bounds[0] + screen_bounds[1] + 2.0 * radius;
double full_h = screen_bounds[2] + screen_bounds[3] + 2.0 * radius;
// Subtract from the full width to get the width of the square
// enclosing the circle slice from the sphere in the plane
// through the center of the sphere. If the screen bounds for
// the left and right planes (0,1) are greater than zero, then
// the edge of the sphere was a positive distance away from the
// plane, so there is a gap between the edge of the plane and
// the edge of the box.
double part_w = full_w;
if ( screen_bounds[0] > 0.0 )
{
part_w -= screen_bounds[0];
}
if ( screen_bounds[1] > 0.0 )
{
part_w -= screen_bounds[1];
}
// Do the same thing for the height with the top and bottom
// planes (2,3).
double part_h = full_h;
if ( screen_bounds[2] > 0.0 )
{
part_h -= screen_bounds[2];
}
if ( screen_bounds[3] > 0.0 )
{
part_h -= screen_bounds[3];
}
// Compute the fraction of coverage
if ((full_w * full_h)!=0.0)
{
return (part_w * part_h) / (full_w * full_h);
}
return 0;
}
}
class vtkAMRStreamingPriorityQueue::vtkInternals
{
public:
class vtkPriorityQueueItem
{
public:
unsigned int BlockId;
double Priority;
vtkPriorityQueueItem() : BlockId(0), Priority(0)
{
}
bool operator < (const vtkPriorityQueueItem& other) const
{
return this->Priority < other.Priority;
}
};
typedef std::priority_queue<vtkPriorityQueueItem> PriorityQueueType;
PriorityQueueType PriorityQueue;
vtkSmartPointer<vtkAMRInformation> AMRMetadata;
};
vtkStandardNewMacro(vtkAMRStreamingPriorityQueue);
//----------------------------------------------------------------------------
vtkAMRStreamingPriorityQueue::vtkAMRStreamingPriorityQueue()
{
this->Internals = new vtkInternals();
}
//----------------------------------------------------------------------------
vtkAMRStreamingPriorityQueue::~vtkAMRStreamingPriorityQueue()
{
delete this->Internals;
this->Internals = 0;
}
//----------------------------------------------------------------------------
void vtkAMRStreamingPriorityQueue::Initialize(vtkAMRInformation* amr)
{
delete this->Internals;
this->Internals = new vtkInternals();
this->Internals->AMRMetadata = amr;
for (unsigned int cc=0; cc < amr->GetTotalNumberOfBlocks(); cc++)
{
vtkInternals::vtkPriorityQueueItem item;
item.BlockId = cc;
item.Priority = (amr->GetTotalNumberOfBlocks() - cc);
// default priority is to prefer lower levels. Thus even without
// view-planes we have reasonable priority.
this->Internals->PriorityQueue.push(item);
}
}
//----------------------------------------------------------------------------
bool vtkAMRStreamingPriorityQueue::IsEmpty()
{
return this->Internals->PriorityQueue.empty();
}
//----------------------------------------------------------------------------
unsigned int vtkAMRStreamingPriorityQueue::Pop()
{
if (this->IsEmpty())
{
vtkErrorMacro("Queue is empty!");
return 0;
}
vtkInternals::vtkPriorityQueueItem item =
this->Internals->PriorityQueue.top();
this->Internals->PriorityQueue.pop();
return item.BlockId;
}
//----------------------------------------------------------------------------
void vtkAMRStreamingPriorityQueue::Update(const double view_planes[24])
{
if (!this->Internals->AMRMetadata)
{
return;
}
vtkInternals::PriorityQueueType current_queue;
std::swap(current_queue, this->Internals->PriorityQueue);
for (;!current_queue.empty(); current_queue.pop())
{
vtkInternals::vtkPriorityQueueItem item = current_queue.top();
unsigned int level=0, index=0;
this->Internals->AMRMetadata->ComputeIndexPair(
item.BlockId, level, index);
double block_bounds[6];
this->Internals->AMRMetadata->GetBounds(level, index, block_bounds);
double center[3];
center[0] = (block_bounds[0] + block_bounds[1]) / 2.0;
center[1] = (block_bounds[2] + block_bounds[3]) / 2.0;
center[2] = (block_bounds[4] + block_bounds[5]) / 2.0;
double distance;
double coverage = vtkComputeScreenCoverage(
view_planes, block_bounds, distance);
item.Priority = coverage * coverage /
( 1 + level * level + distance);
this->Internals->PriorityQueue.push(item);
}
}
//----------------------------------------------------------------------------
void vtkAMRStreamingPriorityQueue::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
/*=========================================================================
Program: ParaView
Module: $RCSfile$
Copyright (c) Kitware, Inc.
All rights reserved.
See Copyright.txt or http://www.paraview.org/HTML/Copyright.html 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.
=========================================================================*/
// .NAME vtkAMRStreamingPriorityQueue - implements a coverage based priority
// queue for vtkOverlappingAMR dataset.
// .SECTION Description
// vtkAMRStreamingPriorityQueue is used by representations supporting streaming
// of AMR datasets to determine the priorities for blocks in the dataset. This
// class relies on the bounds information provided by the AMR meta-data i.e.
// vtkAMRInformation. This class support view-based priority computation. Simply
// provide the view planes (returned by vtkCamera::GetFrustumPlanes()) to the
// vtkAMRStreamingPriorityQueue::Update() call to update the prorities for the
// blocks currently in the queue.
// .SECTION See Also
// vtkAMROutlineRepresentation, vtkAMRStreamingVolumeRepresentation.
#ifndef __vtkAMRStreamingPriorityQueue_h
#define __vtkAMRStreamingPriorityQueue_h
#include "vtkPVClientServerCoreRenderingModule.h" // for export macros
#include "vtkObject.h"
class vtkAMRInformation;
class VTKPVCLIENTSERVERCORERENDERING_EXPORT vtkAMRStreamingPriorityQueue : public vtkObject
{
public:
static vtkAMRStreamingPriorityQueue* New();
vtkTypeMacro(vtkAMRStreamingPriorityQueue, vtkObject);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// Initializes the queue. All information about items in the is lost.
void Initialize(vtkAMRInformation* amr);
// Description:
// Updates the priorities of blocks based on the new view frustum planes.
// Information about blocks "popped" from the queue is preserved and those
// blocks are not reinserted in the queue.
void Update(const double view_planes[24]);
// Description:
// Returns if the queue is empty.
bool IsEmpty();
// Description:
// Pops and returns of composite id for the block at the top of the queue.
// Test if the queue is empty before calling this method.
unsigned int Pop();
//BTX
protected:
vtkAMRStreamingPriorityQueue();
~vtkAMRStreamingPriorityQueue();
private:
vtkAMRStreamingPriorityQueue(const vtkAMRStreamingPriorityQueue&); // Not implemented
void operator=(const vtkAMRStreamingPriorityQueue&); // Not implemented
class vtkInternals;
vtkInternals* Internals;
//ETX
};
#endif
/*=========================================================================
Program: ParaView
Module: $RCSfile$
Copyright (c) Kitware, Inc.
All rights reserved.
See Copyright.txt or http://www.paraview.org/HTML/Copyright.html 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.
=========================================================================*/
// .NAME vtkAMRStreamingVolumeRepresentation - representation used for volume
// rendering AMR datasets with ability to stream blocks.
// .SECTION Description
// vtkAMRStreamingVolumeRepresentation is a representation used for volume
// rendering AMR datasets with ability to stream blocks from the input pipeline.
#ifndef __vtkAMRStreamingVolumeRepresentation_h
#define __vtkAMRStreamingVolumeRepresentation_h
#include "vtkPVDataRepresentation.h"
#include "vtkSmartPointer.h" // needed for vtkSmartPointer.
#include "vtkWeakPointer.h" // needed for vtkSmartPointer.
class vtkAMRStreamingPriorityQueue;
class vtkColorTransferFunction;
class vtkImageData;
class vtkOverlappingAMR;
class vtkPiecewiseFunction;
class vtkPVLODVolume;
class vtkResampledAMRImageSource;
class vtkSmartVolumeMapper;
class vtkVolumeProperty;
class VTKPVCLIENTSERVERCORERENDERING_EXPORT vtkAMRStreamingVolumeRepresentation :
public vtkPVDataRepresentation
{
public:
static vtkAMRStreamingVolumeRepresentation* New();
vtkTypeMacro(vtkAMRStreamingVolumeRepresentation, vtkPVDataRepresentation);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// vtkAlgorithm::ProcessRequest() equivalent for rendering passes. This is
// typically called by the vtkView to request meta-data from the
// representations or ask them to perform certain tasks e.g.
// PrepareForRendering.
// Overridden to skip processing when visibility if off.
virtual int ProcessViewRequest(vtkInformationRequestKey* request_type,
vtkInformation* inInfo, vtkInformation* outInfo);
// Description:
// Get/Set the visibility for this representation. When the visibility of
// representation of false, all view passes are ignored.
virtual void SetVisibility(bool val);
// Description:
// Get/Set the resample buffer size. This controls the resolution at which the
// data is resampled.
void SetNumberOfSamples(int x, int y, int z);
//***************************************************************************
// Scalar coloring API (forwarded for vtkSmartVolumeMapper.
// This is same a vtkDataObject::FieldAssociation types so you can use those
// as well.
enum AttributeTypes
{
POINT_DATA=0,
CELL_DATA=1
};
// Description:
// Methods to control scalar coloring. ColorAttributeType defines the
// attribute type.
void SetColorAttributeType(int val);
// Description:
// Pick the array to color with.
void SetColorArrayName(const char*);
//***************************************************************************
// Forwarded to Actor.
void SetOrientation(double, double, double);
void SetOrigin(double, double, double);
void SetPickable(int val);
void SetPosition(double, double, double);
void SetScale(double, double, double);
//***************************************************************************
// Forwarded to vtkVolumeProperty.
void SetInterpolationType(int val);
void SetColor(vtkColorTransferFunction* lut);
void SetScalarOpacity(vtkPiecewiseFunction* pwf);
void SetScalarOpacityUnitDistance(double val);
void SetAmbient(double);
void SetDiffuse(double);
void SetSpecular(double);
void SetSpecularPower(double);
void SetShade(bool);
void SetIndependantComponents(bool);
//***************************************************************************
// Forwarded to vtkSmartVolumeMapper.
void SetRequestedRenderMode(int);