mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-28 00:17:30 -05:00
OpenCL POC 1
This commit is contained in:
parent
a1a09d75e6
commit
51d1bb36b8
@ -34,9 +34,16 @@ option(USE_OPENCL "Use OpenCL" ON)
|
|||||||
if (USE_OPENCL)
|
if (USE_OPENCL)
|
||||||
FIND_PACKAGE(OpenCL)
|
FIND_PACKAGE(OpenCL)
|
||||||
if(${OpenCL_FOUND})
|
if(${OpenCL_FOUND})
|
||||||
|
<<<<<<< a1a09d75e627b0f085c5a1177db5d58374ca6f44
|
||||||
SET(HAVE_OPENCL TRUE)
|
SET(HAVE_OPENCL TRUE)
|
||||||
else(${OpenCL_FOUND})
|
else(${OpenCL_FOUND})
|
||||||
MESSAGE(STATUS "Couldn't find OpenCL: support DISABLED")
|
MESSAGE(STATUS "Couldn't find OpenCL: support DISABLED")
|
||||||
|
=======
|
||||||
|
SET (USE_OPENCL TRUE CACHE BOOL "Use OpenCL")
|
||||||
|
IF(USE_OPENCL)
|
||||||
|
SET(HAVE_OPENCL TRUE)
|
||||||
|
ENDIF(USE_OPENCL)
|
||||||
|
>>>>>>> OpenCL POC 1
|
||||||
endif(${OpenCL_FOUND})
|
endif(${OpenCL_FOUND})
|
||||||
endif(USE_OPENCL)
|
endif(USE_OPENCL)
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ QgsNineCellFilter::QgsNineCellFilter( const QString &inputFile, const QString &o
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: return an anum instead of an int
|
||||||
int QgsNineCellFilter::processRaster( QgsFeedback *feedback )
|
int QgsNineCellFilter::processRaster( QgsFeedback *feedback )
|
||||||
{
|
{
|
||||||
#ifdef HAVE_OPENCL
|
#ifdef HAVE_OPENCL
|
||||||
@ -52,7 +53,7 @@ int QgsNineCellFilter::processRaster( QgsFeedback *feedback )
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
QgsMessageLog::logMessage( QObject::tr( "Running OpenCL program: %1" )
|
QgsDebugMsg( QObject::tr( "Running OpenCL program: %1" )
|
||||||
.arg( openClProgramBaseName( ) ), QgsOpenClUtils::LOGMESSAGE_TAG, Qgis::Info );
|
.arg( openClProgramBaseName( ) ), QgsOpenClUtils::LOGMESSAGE_TAG, Qgis::Info );
|
||||||
return processRasterGPU( source, feedback );
|
return processRasterGPU( source, feedback );
|
||||||
}
|
}
|
||||||
@ -165,6 +166,7 @@ gdal::dataset_unique_ptr QgsNineCellFilter::openOutputFile( GDALDatasetH inputDa
|
|||||||
|
|
||||||
#ifdef HAVE_OPENCL
|
#ifdef HAVE_OPENCL
|
||||||
|
|
||||||
|
// TODO: return an anum instead of an int
|
||||||
int QgsNineCellFilter::processRasterGPU( const QString &source, QgsFeedback *feedback )
|
int QgsNineCellFilter::processRasterGPU( const QString &source, QgsFeedback *feedback )
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -224,21 +226,25 @@ int QgsNineCellFilter::processRasterGPU( const QString &source, QgsFeedback *fee
|
|||||||
// Cast to float (because double just crashes on some GPUs)
|
// Cast to float (because double just crashes on some GPUs)
|
||||||
std::vector<float> rasterParams;
|
std::vector<float> rasterParams;
|
||||||
|
|
||||||
rasterParams.push_back( mInputNodataValue );
|
rasterParams.push_back( mInputNodataValue ); // 0
|
||||||
rasterParams.push_back( mOutputNodataValue );
|
rasterParams.push_back( mOutputNodataValue ); // 1
|
||||||
rasterParams.push_back( mZFactor );
|
rasterParams.push_back( mZFactor ); // 2
|
||||||
rasterParams.push_back( mCellSizeX );
|
rasterParams.push_back( mCellSizeX ); // 3
|
||||||
rasterParams.push_back( mCellSizeY );
|
rasterParams.push_back( mCellSizeY ); // 4
|
||||||
|
|
||||||
|
// Allow subclasses to add extra params needed for computation:
|
||||||
|
// used to pass additional args to opencl program
|
||||||
addExtraRasterParams( rasterParams );
|
addExtraRasterParams( rasterParams );
|
||||||
|
|
||||||
std::size_t bufferSize( sizeof( float ) * ( xSize + 2 ) );
|
std::size_t bufferSize( sizeof( float ) * ( xSize + 2 ) );
|
||||||
|
std::size_t inputSize( sizeof( float ) * ( xSize ) );
|
||||||
|
|
||||||
cl::Buffer rasterParamsBuffer( queue, rasterParams.begin(), rasterParams.end(), true, false, nullptr );
|
cl::Buffer rasterParamsBuffer( queue, rasterParams.begin(), rasterParams.end(), true, false, nullptr );
|
||||||
cl::Buffer scanLine1Buffer( ctx, CL_MEM_READ_ONLY, bufferSize, nullptr, nullptr );
|
cl::Buffer scanLine1Buffer( ctx, CL_MEM_READ_ONLY, bufferSize, nullptr, nullptr );
|
||||||
cl::Buffer scanLine2Buffer( ctx, CL_MEM_READ_ONLY, bufferSize, nullptr, nullptr );
|
cl::Buffer scanLine2Buffer( ctx, CL_MEM_READ_ONLY, bufferSize, nullptr, nullptr );
|
||||||
cl::Buffer scanLine3Buffer( ctx, CL_MEM_READ_ONLY, bufferSize, nullptr, nullptr );
|
cl::Buffer scanLine3Buffer( ctx, CL_MEM_READ_ONLY, bufferSize, nullptr, nullptr );
|
||||||
cl::Buffer resultLineBuffer( ctx, CL_MEM_WRITE_ONLY, sizeof( float ) * xSize, nullptr, nullptr );
|
cl::Buffer *scanLineBuffer[3] = {&scanLine1Buffer, &scanLine2Buffer, &scanLine3Buffer};
|
||||||
|
cl::Buffer resultLineBuffer( ctx, CL_MEM_WRITE_ONLY, inputSize, nullptr, nullptr );
|
||||||
|
|
||||||
// Create a program from the kernel source
|
// Create a program from the kernel source
|
||||||
cl::Program program( QgsOpenClUtils::buildProgram( ctx, source, QgsOpenClUtils::ExceptionBehavior::Throw ) );
|
cl::Program program( QgsOpenClUtils::buildProgram( ctx, source, QgsOpenClUtils::ExceptionBehavior::Throw ) );
|
||||||
@ -252,6 +258,9 @@ int QgsNineCellFilter::processRasterGPU( const QString &source, QgsFeedback *fee
|
|||||||
cl::Buffer &
|
cl::Buffer &
|
||||||
> ( program, "processNineCellWindow" );
|
> ( program, "processNineCellWindow" );
|
||||||
|
|
||||||
|
// Rotate buffer index
|
||||||
|
std::vector<int> rowIndex = {0, 1, 2};
|
||||||
|
|
||||||
// values outside the layer extent (if the 3x3 window is on the border) are sent to the processing method as (input) nodata values
|
// values outside the layer extent (if the 3x3 window is on the border) are sent to the processing method as (input) nodata values
|
||||||
for ( int i = 0; i < ySize; ++i )
|
for ( int i = 0; i < ySize; ++i )
|
||||||
{
|
{
|
||||||
@ -267,22 +276,23 @@ int QgsNineCellFilter::processRasterGPU( const QString &source, QgsFeedback *fee
|
|||||||
|
|
||||||
if ( i == 0 )
|
if ( i == 0 )
|
||||||
{
|
{
|
||||||
// Fill scanline 1 with (input) nodata for the values above the first row and feed scanline2 with the first row
|
// Fill scanline 1 with (input) nodata for the values above the first row and
|
||||||
|
// feed scanline2 with the first actual data row
|
||||||
for ( int a = 0; a < xSize + 2 ; ++a )
|
for ( int a = 0; a < xSize + 2 ; ++a )
|
||||||
{
|
{
|
||||||
scanLine[a] = mInputNodataValue;
|
scanLine[a] = mInputNodataValue;
|
||||||
}
|
}
|
||||||
queue.enqueueWriteBuffer( scanLine1Buffer, CL_TRUE, 0, bufferSize, scanLine.get() );
|
queue.enqueueWriteBuffer( scanLine1Buffer, CL_TRUE, 0, bufferSize, scanLine.get() );
|
||||||
|
|
||||||
// Read scanline2
|
// Read scanline2: first real raster row
|
||||||
if ( GDALRasterIO( rasterBand, GF_Read, 0, 0, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
|
if ( GDALRasterIO( rasterBand, GF_Read, 0, i, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
|
||||||
{
|
{
|
||||||
QgsDebugMsg( "Raster IO Error" );
|
QgsDebugMsg( "Raster IO Error" );
|
||||||
}
|
}
|
||||||
queue.enqueueWriteBuffer( scanLine2Buffer, CL_TRUE, 0, bufferSize, scanLine.get() );
|
queue.enqueueWriteBuffer( scanLine2Buffer, CL_TRUE, 0, bufferSize, scanLine.get() );
|
||||||
|
|
||||||
// Read scanline3
|
// Read scanline3: second real raster row
|
||||||
if ( GDALRasterIO( rasterBand, GF_Read, 0, 0, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
|
if ( GDALRasterIO( rasterBand, GF_Read, 0, i + 1, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
|
||||||
{
|
{
|
||||||
QgsDebugMsg( "Raster IO Error" );
|
QgsDebugMsg( "Raster IO Error" );
|
||||||
}
|
}
|
||||||
@ -291,17 +301,14 @@ int QgsNineCellFilter::processRasterGPU( const QString &source, QgsFeedback *fee
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Normally fetch only scanLine3 and move forward one row
|
// Normally fetch only scanLine3 and move forward one row
|
||||||
queue.enqueueCopyBuffer( scanLine2Buffer, scanLine1Buffer, 0, 0, bufferSize, nullptr, nullptr );
|
// Read scanline 3, fill the last row with nodata values if it's the last iteration
|
||||||
queue.enqueueCopyBuffer( scanLine3Buffer, scanLine2Buffer, 0, 0, bufferSize, nullptr, nullptr );
|
|
||||||
|
|
||||||
// Read scanline 3
|
|
||||||
if ( i == ySize - 1 ) //fill the row below the bottom with nodata values
|
if ( i == ySize - 1 ) //fill the row below the bottom with nodata values
|
||||||
{
|
{
|
||||||
for ( int a = 0; a < xSize + 2; ++a )
|
for ( int a = 0; a < xSize + 2; ++a )
|
||||||
{
|
{
|
||||||
scanLine[a] = mInputNodataValue;
|
scanLine[a] = mInputNodataValue;
|
||||||
}
|
}
|
||||||
queue.enqueueWriteBuffer( scanLine3Buffer, CL_TRUE, 0, bufferSize, scanLine.get() ); // row 0
|
queue.enqueueWriteBuffer( *scanLineBuffer[rowIndex[2]], CL_TRUE, 0, bufferSize, scanLine.get() ); // row 0
|
||||||
}
|
}
|
||||||
else // Read line i + 1 and put it into scanline 3
|
else // Read line i + 1 and put it into scanline 3
|
||||||
// Overwrite from input, skip first and last
|
// Overwrite from input, skip first and last
|
||||||
@ -310,7 +317,7 @@ int QgsNineCellFilter::processRasterGPU( const QString &source, QgsFeedback *fee
|
|||||||
{
|
{
|
||||||
QgsDebugMsg( "Raster IO Error" );
|
QgsDebugMsg( "Raster IO Error" );
|
||||||
}
|
}
|
||||||
queue.enqueueWriteBuffer( scanLine3Buffer, CL_TRUE, 0, bufferSize, scanLine.get() ); // row 0
|
queue.enqueueWriteBuffer( *scanLineBuffer[rowIndex[2]], CL_TRUE, 0, bufferSize, scanLine.get() ); // row 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,22 +325,22 @@ int QgsNineCellFilter::processRasterGPU( const QString &source, QgsFeedback *fee
|
|||||||
queue,
|
queue,
|
||||||
cl::NDRange( xSize )
|
cl::NDRange( xSize )
|
||||||
),
|
),
|
||||||
scanLine1Buffer,
|
*scanLineBuffer[rowIndex[0]],
|
||||||
scanLine2Buffer,
|
*scanLineBuffer[rowIndex[1]],
|
||||||
scanLine3Buffer,
|
*scanLineBuffer[rowIndex[2]],
|
||||||
resultLineBuffer,
|
resultLineBuffer,
|
||||||
rasterParamsBuffer
|
rasterParamsBuffer
|
||||||
);
|
);
|
||||||
|
|
||||||
queue.enqueueReadBuffer( resultLineBuffer, CL_TRUE, 0, xSize * sizeof( float ), resultLine.get() );
|
queue.enqueueReadBuffer( resultLineBuffer, CL_TRUE, 0, inputSize, resultLine.get() );
|
||||||
|
|
||||||
if ( GDALRasterIO( outputRasterBand, GF_Write, 0, i, xSize, 1, resultLine.get(), xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
|
if ( GDALRasterIO( outputRasterBand, GF_Write, 0, i, xSize, 1, resultLine.get(), xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
|
||||||
{
|
{
|
||||||
QgsDebugMsg( "Raster IO Error" );
|
QgsDebugMsg( "Raster IO Error" );
|
||||||
}
|
}
|
||||||
|
std::rotate( rowIndex.begin(), rowIndex.begin() + 1, rowIndex.end() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ( feedback && feedback->isCanceled() )
|
if ( feedback && feedback->isCanceled() )
|
||||||
{
|
{
|
||||||
//delete the dataset without closing (because it is faster)
|
//delete the dataset without closing (because it is faster)
|
||||||
@ -344,6 +351,8 @@ int QgsNineCellFilter::processRasterGPU( const QString &source, QgsFeedback *fee
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: return an anum instead of an int
|
||||||
int QgsNineCellFilter::processRasterCPU( QgsFeedback *feedback )
|
int QgsNineCellFilter::processRasterCPU( QgsFeedback *feedback )
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -450,7 +459,7 @@ int QgsNineCellFilter::processRasterCPU( QgsFeedback *feedback )
|
|||||||
QgsDebugMsg( "Raster IO Error" );
|
QgsDebugMsg( "Raster IO Error" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Set first and last extra colums to nodata
|
// Set first and last extra columns to nodata
|
||||||
scanLine1[0] = scanLine1[xSize + 1] = mInputNodataValue;
|
scanLine1[0] = scanLine1[xSize + 1] = mInputNodataValue;
|
||||||
scanLine2[0] = scanLine2[xSize + 1] = mInputNodataValue;
|
scanLine2[0] = scanLine2[xSize + 1] = mInputNodataValue;
|
||||||
scanLine3[0] = scanLine3[xSize + 1] = mInputNodataValue;
|
scanLine3[0] = scanLine3[xSize + 1] = mInputNodataValue;
|
||||||
|
@ -40,9 +40,8 @@ class ANALYSIS_EXPORT QgsNineCellFilter
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the calculation, reads from mInputFile and stores the result in mOutputFile
|
* Starts the calculation, reads from mInputFile and stores the result in mOutputFile
|
||||||
\param feedback feedback object that receives update and that is checked for cancelation.
|
* \param feedback feedback object that receives update and that is checked for cancelation.
|
||||||
\returns 0 in case of success
|
* \returns 0 in case of success
|
||||||
TODO: return an enum
|
|
||||||
*/
|
*/
|
||||||
int processRaster( QgsFeedback *feedback = nullptr );
|
int processRaster( QgsFeedback *feedback = nullptr );
|
||||||
|
|
||||||
@ -60,8 +59,23 @@ class ANALYSIS_EXPORT QgsNineCellFilter
|
|||||||
void setOutputNodataValue( double value ) { mOutputNodataValue = value; }
|
void setOutputNodataValue( double value ) { mOutputNodataValue = value; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates output value from nine input values. The input values and the output value can be equal to the
|
* Calculates output value from nine input values. The input values and the output
|
||||||
nodata value if not present or outside of the border. Must be implemented by subclasses*/
|
* value can be equal to the nodata value if not present or outside of the border.
|
||||||
|
* Must be implemented by subclasses.
|
||||||
|
*
|
||||||
|
* First index of the input cell is the row, second index is the column
|
||||||
|
*
|
||||||
|
* @param x11 surrounding cell top left
|
||||||
|
* @param x21 surrounding cell central left
|
||||||
|
* @param x31 surrounding cell bottom left
|
||||||
|
* @param x12 surrounding cell top central
|
||||||
|
* @param x22 the central cell for which the value will be calculated
|
||||||
|
* @param x32 surrounding cell bottom central
|
||||||
|
* @param x13 surrounding cell top right
|
||||||
|
* @param x23 surrounding cell central right
|
||||||
|
* @param x33 surrounding cell bottom right
|
||||||
|
* @return the calculated cell value for the central cell x22
|
||||||
|
*/
|
||||||
virtual float processNineCellWindow( float *x11, float *x21, float *x31,
|
virtual float processNineCellWindow( float *x11, float *x21, float *x31,
|
||||||
float *x12, float *x22, float *x32,
|
float *x12, float *x22, float *x32,
|
||||||
float *x13, float *x23, float *x33 ) = 0;
|
float *x13, float *x23, float *x33 ) = 0;
|
||||||
@ -85,9 +99,8 @@ class ANALYSIS_EXPORT QgsNineCellFilter
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief processRasterCPU executes the computation on the CPU
|
* \brief processRasterCPU executes the computation on the CPU
|
||||||
* \param feedback
|
* \param feedback instance of QgsFeedback, to allow for progress monitoring and cancelation
|
||||||
* \return an opaque integer for error codes: 0 in case of success
|
* \return an opaque integer for error codes: 0 in case of success
|
||||||
* TODO: return an enum
|
|
||||||
*/
|
*/
|
||||||
int processRasterCPU( QgsFeedback *feedback = nullptr );
|
int processRasterCPU( QgsFeedback *feedback = nullptr );
|
||||||
|
|
||||||
@ -95,12 +108,17 @@ class ANALYSIS_EXPORT QgsNineCellFilter
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief processRasterGPU executes the computation on the GPU
|
* \brief processRasterGPU executes the computation on the GPU
|
||||||
* \param feedback
|
* \param source path to the OpenCL source file
|
||||||
|
* \param feedback instance of QgsFeedback, to allow for progress monitoring and cancelation
|
||||||
* \return an opaque integer for error codes: 0 in case of success
|
* \return an opaque integer for error codes: 0 in case of success
|
||||||
* TODO: return an enum
|
|
||||||
*/
|
*/
|
||||||
int processRasterGPU( const QString &source, QgsFeedback *feedback = nullptr );
|
int processRasterGPU( const QString &source, QgsFeedback *feedback = nullptr );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief addExtraRasterParams allow derived classes to add parameters needed
|
||||||
|
* by OpenCL program
|
||||||
|
* \param params vector of parameters passed to OpenCL algorithm
|
||||||
|
*/
|
||||||
virtual void addExtraRasterParams( std::vector<float> ¶ms )
|
virtual void addExtraRasterParams( std::vector<float> ¶ms )
|
||||||
{
|
{
|
||||||
Q_UNUSED( params );
|
Q_UNUSED( params );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user