Commit fb3550f9 authored by loring's avatar loring

ordered compositing

add alpha blend compositing to visit and use it to implement
ordered compositing. there is some logic to enable it automatically
and a gui option to explicitly disable it. it is on by default.
I also added an option for enabling depth peeling. this is off by
default because it's very slow. I changed all GetCell methods to
return long long so that overflow is less of an issue. I fixed a bug
in the transparency actor that was causing transparent geometry
to be sorted twice.


git-svn-id: http://visit.ilight.com/svn/visit/trunk/src@27514 18c085ea-50e0-402c-830e-de6fd14e8384
parent 91efe5c6
......@@ -389,6 +389,9 @@
# Matthieu Dorier via Cyrus Harrison, Thu Aug 20 09:07:08 PDT 2015
# Added Damaris support.
#
# Burlen Loring, Thu Oct 8 10:45:36 PDT 2015
# Added define for aligned_alloc in visit-config.h
#
#****************************************************************************/
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8 FATAL_ERROR)
......@@ -1959,6 +1962,7 @@ CHECK_FUNCTION_EXISTS(memmove HAVE_MEMMOVE)
CHECK_FUNCTION_EXISTS(div HAVE_DIV)
CHECK_FUNCTION_EXISTS(setenv HAVE_SETENV)
CHECK_FUNCTION_EXISTS(strtof HAVE_STRTOF)
CHECK_FUNCTION_EXISTS(aligned_alloc HAVE_ALIGNED_ALLOC)
CHECK_STRTOF_PROTOTYPE(HAVE_STRTOF_PROTOTYPE)
CHECK_FTIME_PROTOTYPE(HAVE_FTIME_PROTOTYPE)
CHECK_ISFINITE_EXISTS(HAVE_ISFINITE)
......@@ -1972,6 +1976,8 @@ IF(NOT VISIT_DISABLE_SELECT)
ENDIF(WIN32)
ENDIF(NOT VISIT_DISABLE_SELECT)
# Set the rendering size limit to 16384 so that we are not unnecessarily
# constraining the user. There is no way to set this properly since this
# is used in the viewer and the limit really comes from the engine, which
......
......@@ -47,6 +47,8 @@
#include <avtImageCompositer.h>
#include <avtParallel.h>
#include <ImproperUseException.h>
#include <sstream>
using std::ostringstream;
// ****************************************************************************
// Method: avtImageCompositer constructor
......@@ -118,17 +120,31 @@ void avtImageCompositer::GetOutputImageSize(int *numRows, int *numCols) const
//
// Programmer: Mark C. Miller
// Creation: February 18, 2003
//
// Modifications:
//
// Burlen Loring, Thu Oct 8 10:47:58 PDT 2015
// Report some information in the error message about what
// the problem is.
//
// ****************************************************************************
void avtImageCompositer::AddImageInput(avtImage_p image,
int rowOffset, int colOffset)
{
avtImageRepresentation& imageRep = image->GetImage();
int imageRows, imageCols;
imageRep.GetSize(&imageRows, &imageCols);
if ((imageRows + rowOffset > outRows) || (imageCols + colOffset > outCols))
EXCEPTION0(ImproperUseException);
imageRep.SetOrigin(rowOffset, colOffset);
inputImages.push_back(image);
avtImageRepresentation& imageRep = image->GetImage();
int imageRows, imageCols;
imageRep.GetSize(&imageRows, &imageCols);
if ((imageRows + rowOffset > outRows) || (imageCols + colOffset > outCols))
{
ostringstream oss;
oss << "Bounds error in avtImageCompositer::AddImageInput "
<< "imageRows = " << imageRows << " rowOffset = " << rowOffset
<< " outRows = " << outRows << " imageCols = " << imageCols
<< " colOffset = " << colOffset << " outCols = " << outCols;
EXCEPTION1(ImproperUseException, oss.str().c_str());
}
imageRep.SetOrigin(rowOffset, colOffset);
inputImages.push_back(image);
}
// ****************************************************************************
......
......@@ -48,6 +48,8 @@
#include <avtTiledImageCompositor.h>
#include <vtkImageData.h>
#include <ImproperUseException.h>
#include <vector>
using std::vector;
#ifdef PARALLEL
// ****************************************************************************
......@@ -60,18 +62,25 @@
// compositing.
//
// NOTE: THIS CODE IS DUPLICATED IN vtkParallelImageSpaceRedistributor.C
// TODO -- put this code in 1 place
// TODO -- what happens there are more ranks than the image is tall??
//
// Programmer: Jeremy Meredith
// Creation: September 1, 2004
//
// Modifications:
//
// Burlen Loring, Thu Oct 8 10:50:10 PDT 2015
// use array to store the extent
//
// ****************************************************************************
static void AreaOwned(int rank, int size, int w, int h,
int &x1,int &y1, int &x2,int &y2)
static
void AreaOwned(int rank, int nranks, int w, int h, int *ext)
{
x1 = 0;
x2 = w;
y1 = (h*rank)/size;
y2 = ((h*(rank+1))/size);
ext[0] = 0;
ext[1] = w - 1;
ext[2] = (h*rank)/nranks;
ext[3] = ((h*(rank+1))/nranks) - 1;
}
#endif
......@@ -83,12 +92,14 @@ static void AreaOwned(int rank, int size, int w, int h,
//
// Modifications:
//
// Burlen Loring, Thu Oct 8 10:49:35 PDT 2015
// Use an initializer list
//
// ****************************************************************************
avtTiledImageCompositor::avtTiledImageCompositor()
{
chunkSize = 1000000;
}
: chunkSize(1000000), bcastResult(false)
{}
// ****************************************************************************
......@@ -120,14 +131,23 @@ avtTiledImageCompositor::~avtTiledImageCompositor()
//
// Mark C. Miller, Mon Jan 22 22:09:01 PST 2007
// Changed MPI_COMM_WORLD to VISIT_MPI_COMM
//
// Burlen Loring, Fri Sep 11 01:15:02 PDT 2015
// Eliminated communication of tile sizes as these can
// be computed locally. Added the ability to broadcast
// the result to all ranks.
//
// ****************************************************************************
int getNumPixels(int *ext)
{ return (ext[1] - ext[0] + 1)*(ext[3] - ext[2] + 1); }
void
avtTiledImageCompositor::Execute(void)
{
#ifdef PARALLEL
int rank = PAR_Rank();
int size = PAR_Size();
int nranks = PAR_Size();
if (inputImages.size() != 1)
{
......@@ -135,63 +155,54 @@ avtTiledImageCompositor::Execute(void)
"only a single input image per processor.");
}
// Get the whole image size
// Get the whole image nranks
int width, height;
inputImages[0]->GetImage().GetSize(&height, &width);
// Figure out how much of the screen I own
int x1,y1,x2,y2;
AreaOwned(rank, size, width, height, x1,y1,x2,y2);
int mywidth = x2 - x1;
int myheight = y2 - y1;
unsigned char *inrgb = inputImages[0]->GetImage().GetRGBBuffer();
// get the tile extents
vector<int> offs(nranks, 0);
vector<int> sizes(nranks, 0);
vector<int> tile(4*nranks, 0);
for (int i = 0, q = 0; i < nranks; ++i)
{
AreaOwned(i, nranks, width, height, &tile[4*i]);
int n = 3*getNumPixels(&tile[4*i]);
sizes[i] = n;
offs[i] = q;
q += n;
}
// Create an output image if we are the root process
vtkImageData *outputImageData = NULL;
unsigned char *outrgb = NULL;
if (rank == mpiRoot)
if (bcastResult || (rank == mpiRoot))
{
outputImageData = avtImageRepresentation::NewImage(width, height);
outrgb = (unsigned char *)outputImageData->GetScalarPointer(0,0,0);
}
// Determine how many pixels need to be sent by each process
// Note -- count is for each RGB component separately (thus the "*3")
int pixelSize = mywidth * myheight * 3;
int *pixelSizes = (rank == mpiRoot) ? new int[size] : NULL;
MPI_Gather(&pixelSize, 1, MPI_INT, pixelSizes, 1, MPI_INT,
mpiRoot, VISIT_MPI_COMM);
// Count 'em up
// ... okay, so there's probably no point ....
// get the input
unsigned char *inrgb = inputImages[0]->GetImage().GetRGBBuffer();
// Gather the pixels
int *displacements = NULL;
if (rank == mpiRoot)
if (bcastResult)
{
displacements = new int[size];
displacements[0] = 0;
for (int i=1; i<size; i++)
{
displacements[i] = displacements[i-1] + pixelSizes[i-1];
}
MPI_Allgatherv(inrgb + offs[rank], sizes[rank] , MPI_UNSIGNED_CHAR,
outrgb, &sizes[0], &offs[0], MPI_UNSIGNED_CHAR, VISIT_MPI_COMM);
}
else
{
MPI_Gatherv(inrgb + offs[rank], sizes[rank] , MPI_UNSIGNED_CHAR,
outrgb, &sizes[0], &offs[0], MPI_UNSIGNED_CHAR, mpiRoot,
VISIT_MPI_COMM);
}
// NOTE: assumes all pixels are contiguous in memory!
MPI_Gatherv(&inrgb[3*(width*y1+x1)], pixelSize, MPI_UNSIGNED_CHAR,
outrgb, pixelSizes, displacements, MPI_UNSIGNED_CHAR,
mpiRoot, VISIT_MPI_COMM);
// Set the output
avtImageRepresentation theOutput(outputImageData);
SetOutputImage(theOutput);
// Free the memory (yes, it is safe not to check for NULL in C++)
// Free the memory
if (outputImageData != NULL)
outputImageData->Delete();
delete[] pixelSizes;
delete[] displacements;
#else
SetOutputImage(inputImages[0]->GetImage());
#endif
......
......@@ -60,6 +60,12 @@
// Programmer: Jeremy Meredith
// Creation: August 30, 2004
//
// Modifications:
//
// Burlen Loring, Wed Sep 9 12:54:39 PDT 2015
// Add flag to broadcast the result, consistent with the other avt
// compositring classes
//
// ****************************************************************************
class AVTFILTERS_API avtTiledImageCompositor : public avtImageCompositer
......@@ -76,8 +82,12 @@ class AVTFILTERS_API avtTiledImageCompositor : public avtImageCompositer
void Execute();
void SetAllProcessorsNeedResult(bool v)
{ bcastResult = v; }
private:
int chunkSize;
bool bcastResult;
};
inline const char* avtTiledImageCompositor::GetType()
......
......@@ -76,55 +76,53 @@
// Tom Fogal, Fri Oct 24 20:04:04 MDT 2008
// Add GetAllProcessorsNeedResult method.
//
// Burlen Loring, Mon Aug 24 16:07:26 PDT 2015
// Initialize all meber vars via initializer list
//
// Burlen Loring, Mon Aug 31 14:00:48 PDT 2015
// Added method for setting background color from double[3]
//
// ****************************************************************************
class AVTFILTERS_API avtWholeImageCompositer : public avtImageCompositer
{
public:
avtWholeImageCompositer() {
chunkSize = 1000000;
bg_r = 255; bg_g = 255; bg_b = 255; };
avtWholeImageCompositer() :
allReduce(false), chunkSize(1000000),
bg_r(255), bg_g(255), bg_b(255) {}
virtual ~avtWholeImageCompositer() {};
void SetChunkSize(const int chunkSize);
int GetChunkSize() const;
void SetChunkSize(const int _chunkSize)
{ chunkSize = _chunkSize; }
int GetChunkSize() const
{ return chunkSize; }
void SetBackground(const double *rgb)
{ bg_r = rgb[0]*255.0;
bg_g = rgb[1]*255.0;
bg_b = rgb[2]*255.0; }
void SetBackground(unsigned char r,
unsigned char g,
unsigned char b);
void SetAllProcessorsNeedResult(bool);
bool GetAllProcessorsNeedResult() const;
unsigned char b)
{ bg_r = r; bg_g = g; bg_b = b; }
void SetAllProcessorsNeedResult(bool all)
{ allReduce = all; }
bool GetAllProcessorsNeedResult() const
{ return allReduce; }
virtual void Execute() = 0;
protected:
bool allReduce;
int chunkSize;
unsigned char bg_r;
unsigned char bg_g;
unsigned char bg_b;
};
inline void avtWholeImageCompositer::SetChunkSize(const int _chunkSize)
{ chunkSize = _chunkSize; }
inline int avtWholeImageCompositer::GetChunkSize() const
{ return chunkSize; }
inline void avtWholeImageCompositer::SetBackground(unsigned char r,
unsigned char g,
unsigned char b)
{ bg_r = r; bg_g = g; bg_b = b; }
inline void avtWholeImageCompositer::SetAllProcessorsNeedResult(bool all)
{
allReduce = all;
}
inline bool avtWholeImageCompositer::GetAllProcessorsNeedResult() const
{
return allReduce;
}
#endif
......@@ -95,13 +95,18 @@ avtCellList::avtCellList(int nv)
// Programmer: Hank Childs
// Creation: January 27, 2001
//
// Modifications:
//
// Burlen Loring, Sun Sep 6 14:58:03 PDT 2015
// Changed the return type of GetNumberOfCells to long long
//
// ****************************************************************************
avtCellList::~avtCellList()
{
if (celllist != NULL)
{
for (int i = 0 ; i < celllistI ; i++)
for (long long i = 0 ; i < celllistI ; ++i)
{
if (celllist[i] != NULL)
{
......@@ -291,6 +296,11 @@ avtCellList::Store(const avtPoint &pt, int minx, int maxx, int miny,
// Programmer: Hank Childs
// Creation: January 27, 2001
//
// Modifications:
//
// Burlen Loring, Sun Sep 6 14:58:03 PDT 2015
// Changed the return type of GetNumberOfCells to long long
//
// ****************************************************************************
void
......@@ -308,7 +318,7 @@ avtCellList::Store(char *cell, int minx, int maxx, int miny, int maxy,int size)
{
celllistN *= 2;
avtSerializedCell **newlist = new avtSerializedCell*[celllistN];
for (int i = 0 ; i < celllistI ; i++)
for (long long i = 0 ; i < celllistI ; ++i)
{
newlist[i] = celllist[i];
}
......@@ -349,7 +359,7 @@ avtCellList::Store(char *cell, int minx, int maxx, int miny, int maxy,int size)
// ****************************************************************************
char *
avtCellList::Serialize(const double (*pts)[3],
avtCellList::Serialize(const double (*pts)[3],
const double (*var)[AVT_VARIABLE_LIMIT], int nvals)
{
int numPoints = 3;
......@@ -423,12 +433,14 @@ avtCellList::SerializePoint(const double *bbox, const double *var)
// Hank Childs, Wed Jan 25 07:15:38 PST 2006
// Add support for points.
//
// Burlen Loring, Sun Sep 6 14:58:03 PDT 2015
// Changed the return type of GetNumberOfCells to long long
//
// ****************************************************************************
char *
avtCellList::ConstructMessages(avtImagePartition *part, char **msgs, int *lens)
{
int i, j;
int numPartitions = part->GetNumPartitions();
int storageForCoord = 3;
......@@ -439,12 +451,12 @@ avtCellList::ConstructMessages(avtImagePartition *part, char **msgs, int *lens)
//
// Set up memory to put our messages into.
//
for (i = 0 ; i < numPartitions ; i++)
for (long long i = 0 ; i < numPartitions ; ++i)
{
lens[i] = 0;
}
int *partitions = new int[numPartitions];
for (i = 0 ; i < celllistI ; i++)
for (long long i = 0 ; i < celllistI ; ++i)
{
//
// PartitionList will make a list of the partitions that this cell
......@@ -458,14 +470,14 @@ avtCellList::ConstructMessages(avtImagePartition *part, char **msgs, int *lens)
size += bytesPerNode*celllist[i]->size;
else
size += bytesForCellThatIsAPt;
for (j = 0 ; j < numParts ; j++)
for (int j = 0 ; j < numParts ; j++)
{
lens[partitions[j]] += size;
}
}
char *rv = CreateMessageStrings(msgs, lens, numPartitions);
char **msgstemp = new char*[numPartitions];
for (i = 0 ; i < numPartitions ; i++)
for (long long i = 0 ; i < numPartitions ; ++i)
{
msgstemp[i] = msgs[i];
}
......@@ -473,12 +485,12 @@ avtCellList::ConstructMessages(avtImagePartition *part, char **msgs, int *lens)
//
// Go through our cell list and add each cell to the appropriate message.
//
for (i = 0 ; i < celllistI ; i++)
for (long long i = 0 ; i < celllistI ; ++i)
{
int numParts = part->PartitionList(celllist[i]->minx,celllist[i]->maxx,
celllist[i]->miny,celllist[i]->maxy,
partitions);
for (j = 0 ; j < numParts ; j++)
for (int j = 0 ; j < numParts ; j++)
{
int p = partitions[j];
InlineCopy(msgstemp[p], (char *)&(celllist[i]->size), sizeof(int));
......@@ -692,12 +704,17 @@ avtCellList::UnserializePoint(double *bbox, double *var, const char *&str)
// Programmer: Hank Childs
// Creation: January 1, 2002
//
// Modifications:
//
// Burlen Loring, Sun Sep 6 14:58:03 PDT 2015
// Changed the return type of GetNumberOfCells to long long
//
// ****************************************************************************
void
avtCellList::EstimateNumberOfSamplesPerScanline(int *samples)
{
for (int i = 0 ; i < celllistI ; i++)
for (long long i = 0 ; i < celllistI ; i++)
{
const avtSerializedCell *cell = celllist[i];
......
......@@ -99,6 +99,9 @@ typedef struct
// Define private copy constructor and assignment operator to prevent
// accidental use of default, bitwise copy implementations.
//
// Burlen Loring, Sun Sep 6 14:58:03 PDT 2015
// Changed the return type of GetNumberOfCells to long long
//
// ****************************************************************************
class PIPELINE_API avtCellList
......@@ -118,7 +121,7 @@ class PIPELINE_API avtCellList
char *ConstructMessages(avtImagePartition *, char **,
int *);
void EstimateNumberOfSamplesPerScanline(int *);
int GetNumberOfCells(void) const { return celllistI; };
long long GetNumberOfCells(void) const { return celllistI; };
void Restrict(int, int, int, int);
......@@ -126,8 +129,8 @@ class PIPELINE_API avtCellList
protected:
avtSerializedCell **celllist;
int celllistI;
int celllistN;
long long celllistI;
long long celllistN;
int nVars;
bool useRestriction;
......
......@@ -90,6 +90,9 @@ class avtWebpage;
// Hank Childs, Mon Feb 2 09:26:16 PST 2009
// Added data member for the contract from a previous execution.
//
// Burlen Loring, Sun Sep 6 14:58:03 PDT 2015
// Changed the return type of GetNumberOfCells to long long
//
// ****************************************************************************
class PIPELINE_API avtDataObject
......@@ -107,7 +110,7 @@ class PIPELINE_API avtDataObject
avtDataObjectInformation &GetInfo(void) { return info; };
const avtDataObjectInformation &GetInfo(void) const { return info; };
virtual int GetNumberOfCells(bool polysOnly = false)
virtual long long GetNumberOfCells(bool polysOnly = false)
const = 0;
virtual const char *GetType(void) = 0;
......
......@@ -552,26 +552,31 @@ avtDataRepresentation::Valid(void)
//
// Modifications:
//
// Mark C. Miller, Wed Nov 5 09:48:13 PST 2003
// Added option to count polygons only
// Mark C. Miller, Wed Nov 5 09:48:13 PST 2003
// Added option to count polygons only
//
// Cameron Christensen, Thursday, May 22, 2014
// Added support for EAVL.
//
// Burlen Loring, Sun Sep 6 14:58:03 PDT 2015
// Changed the return type of GetNumberOfCells to long long
//
// ****************************************************************************
int
long long
avtDataRepresentation::GetNumberOfCells(int topoDim, bool polysOnly) const
{
if (asVTK == NULL && asEAVL == NULL)
{
if (asChar == NULL)
{
EXCEPTION0(NoInputException);
}
return -1;
}
else
{
int numCells = 0;
long long numCells = 0;
#ifdef HAVE_LIBEAVL
if (dataRepType == DATA_REP_TYPE_EAVL)
......@@ -588,18 +593,17 @@ avtDataRepresentation::GetNumberOfCells(int topoDim, bool polysOnly) const
if (polysOnly)
{
if (topoDim < 3)
numCells = (int) asVTK->GetNumberOfCells();
numCells = asVTK->GetNumberOfCells();
else
numCells = 0;
}
else
{
numCells = (int) asVTK->GetNumberOfCells();
numCells = asVTK->GetNumberOfCells();
}
}
return numCells;
return numCells;
}
}
......
......@@ -125,6 +125,9 @@ typedef enum
// I modified the EAVL version of the avtDataRepresentation constructor
// to also have domain and label arguments.
//
// Burlen Loring, Sun Sep 6 14:58:03 PDT 2015
// Changed the return type of GetNumberOfCells to long long
//
// ****************************************************************************
class PIPELINE_API avtDataRepresentation
......@@ -138,6 +141,7 @@ class PIPELINE_API avtDataRepresentation
avtDataRepresentation(char *, int, int, std::string,
CharStrRef &, DataSetType);
avtDataRepresentation(const avtDataRepresentation &);
virtual ~avtDataRepresentation();
avtDataRepresentation &operator=(const avtDataRepresentation &);
......@@ -147,7 +151,7 @@ class PIPELINE_API avtDataRepresentation
vtkDataSet *GetDataVTK(void);
unsigned char *GetDataString(int &, DataSetType &);
unsigned char *GetCompressedDataString(int &, DataSetType &);
int GetNumberOfCells(int topoDim, bool polysOnly) const;
long long GetNumberOfCells(int topoDim, bool polysOnly) const;
float GetCompressionRatio() const;
float GetTimeToCompress() const;
......@@ -189,10 +193,6 @@ class PIPELINE_API avtDataRepresentation
private:
vtkDataSet* EAVLToVTK(eavlDataSet *data);
eavlDataSet* VTKToEAVL(vtkDataSet *data);
};
#endif
......@@ -914,14 +914,17 @@ avtDataTree::GetDataRepresentation()
// Mark C. Miller, Wed Nov 5 09:48:13 PST 2003
// Added optional argument to count polygons only
//
// Burlen Loring, Sun Sep 6 14:58:03 PDT 2015
// Changed the return type of GetNumberOfCells to long long
//
// ****************************************************************************
int
long long
avtDataTree::GetNumberOfCells(int topoDim, bool polysOnly) const
{
if (nChildren > 0)
{
int sum = 0;
long long sum = 0;
for (int i = 0; i < nChildren; i++)
{
if (*children[i] != NULL)
......@@ -933,7 +936,6 @@ avtDataTree::GetNumberOfCells(int topoDim, bool polysOnly) const
{
return dataRep->GetNumberOfCells(topoDim, polysOnly);
}
return 0;
}
......
......@@ -130,6 +130,9 @@ typedef void (*TraverseFunc)(avtDataRepresentation &, void *, bool &);
// Added methods for constructing leaves, to aid in keeping the tree depth
// as shallow as possible.
//
// Burlen Loring, Sun Sep 6 14:58:03 PDT 2015
// Changed the return type of GetNumberOfCells to long long
//
// ****************************************************************************
class PIPELINE_API avtDataTree
......@@ -152,7 +155,7 @@ class PIPELINE_API avtDataTree
avtDataTree(int, avtDataRepresentation **);
avtDataTree(avtDataTree_p, bool dontCopyData = false );
avtDataTree(int, avtDataTree_p *);
virtual ~avtDataTree();
avtDataTree &operator=(const avtDataTree&);
......@@ -160,7 +163,7 @@ class PIPELINE_API avtDataTree
avtDataTree_p GetChild(int);
avtDataRepresentation &GetDataRepresentation(void);
int GetNumberOfCells(int topoDim, bool polysOnly) const;
long long GetNumberOfCells(int topoDim, bool polysOnly) const;
vtkDataSet *GetSingleLeaf(void);
std::string GetDatasetAsString();
......@@ -201,5 +204,4 @@ class PIPELINE_API avtDataTree
void GetUniqueLabels(std::vector<std::string> &, std::set<std::string> &);
};