Skip to content

Commit 08fc641

Browse files
committedAug 8, 2018
CPLAllocator smart wrapper
1 parent a7ef072 commit 08fc641

File tree

4 files changed

+150
-104
lines changed

4 files changed

+150
-104
lines changed
 

‎src/analysis/raster/qgsninecellfilter.cpp

Lines changed: 92 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -221,11 +221,14 @@ int QgsNineCellFilter::processRasterGPU( const QString &source, QgsFeedback *fee
221221
}
222222

223223
//keep only three scanlines in memory at a time, make room for initial and final nodata
224-
float *scanLine1 = ( float * ) CPLMalloc( sizeof( float ) * ( xSize + 2 ) );
225-
float *scanLine2 = ( float * ) CPLMalloc( sizeof( float ) * ( xSize + 2 ) );
226-
float *scanLine3 = ( float * ) CPLMalloc( sizeof( float ) * ( xSize + 2 ) );
224+
QgsOpenClUtils::CPLAllocator<float> scanLine1( xSize + 2 );
225+
QgsOpenClUtils::CPLAllocator<float> scanLine2( xSize + 2 );
226+
QgsOpenClUtils::CPLAllocator<float> scanLine3( xSize + 2 );
227+
//float *scanLine2 = ( float * ) CPLMalloc( sizeof( float ) * ( xSize + 2 ) );
228+
//float *scanLine3 = ( float * ) CPLMalloc( sizeof( float ) * ( xSize + 2 ) );
227229

228-
float *resultLine = ( float * ) CPLMalloc( sizeof( float ) * xSize );
230+
//float *resultLine = ( float * ) CPLMalloc( sizeof( float ) * xSize );
231+
QgsOpenClUtils::CPLAllocator<float> resultLine( xSize );
229232

230233
cl_int errorCode = 0;
231234

@@ -240,123 +243,109 @@ int QgsNineCellFilter::processRasterGPU( const QString &source, QgsFeedback *fee
240243

241244
addExtraRasterParams( rasterParams );
242245

243-
try
244-
{
245246

246-
cl::Buffer rasterParamsBuffer( rasterParams.begin(), rasterParams.end(), true, false, &errorCode );
247-
cl::Buffer scanLine1Buffer( CL_MEM_READ_ONLY, sizeof( float ) * ( xSize + 2 ), nullptr, &errorCode );
248-
cl::Buffer scanLine2Buffer( CL_MEM_READ_ONLY, sizeof( float ) * ( xSize + 2 ), nullptr, &errorCode );
249-
cl::Buffer scanLine3Buffer( CL_MEM_READ_ONLY, sizeof( float ) * ( xSize + 2 ), nullptr, &errorCode );
250-
cl::Buffer resultLineBuffer( CL_MEM_WRITE_ONLY, sizeof( float ) * xSize, nullptr, &errorCode );
251-
252-
// Create a program from the kernel source
253-
cl::Program program( source.toStdString() );
254-
// Use CL 1.1 for compatibility with older libs
255-
program.build( "-cl-std=CL1.1" );
256-
257-
// Create the OpenCL kernel
258-
auto kernel = cl::KernelFunctor <
259-
cl::Buffer &,
260-
cl::Buffer &,
261-
cl::Buffer &,
262-
cl::Buffer &,
263-
cl::Buffer &
264-
> ( program, "processNineCellWindow" );
265-
266-
//values outside the layer extent (if the 3x3 window is on the border) are sent to the processing method as (input) nodata values
267-
for ( int i = 0; i < ySize; ++i )
247+
cl::Buffer rasterParamsBuffer( rasterParams.begin(), rasterParams.end(), true, false, &errorCode );
248+
cl::Buffer scanLine1Buffer( CL_MEM_READ_ONLY, sizeof( float ) * ( xSize + 2 ), nullptr, &errorCode );
249+
cl::Buffer scanLine2Buffer( CL_MEM_READ_ONLY, sizeof( float ) * ( xSize + 2 ), nullptr, &errorCode );
250+
cl::Buffer scanLine3Buffer( CL_MEM_READ_ONLY, sizeof( float ) * ( xSize + 2 ), nullptr, &errorCode );
251+
cl::Buffer resultLineBuffer( CL_MEM_WRITE_ONLY, sizeof( float ) * xSize, nullptr, &errorCode );
252+
253+
// Create a program from the kernel source
254+
cl::Program program( source.toStdString() );
255+
// Use CL 1.1 for compatibility with older libs
256+
program.build( "-cl-std=CL1.1" );
257+
258+
// Create the OpenCL kernel
259+
auto kernel = cl::KernelFunctor <
260+
cl::Buffer &,
261+
cl::Buffer &,
262+
cl::Buffer &,
263+
cl::Buffer &,
264+
cl::Buffer &
265+
> ( program, "processNineCellWindow" );
266+
267+
//values outside the layer extent (if the 3x3 window is on the border) are sent to the processing method as (input) nodata values
268+
for ( int i = 0; i < ySize; ++i )
269+
{
270+
if ( feedback && feedback->isCanceled() )
268271
{
269-
if ( feedback && feedback->isCanceled() )
270-
{
271-
break;
272-
}
272+
break;
273+
}
273274

274-
if ( feedback )
275-
{
276-
feedback->setProgress( 100.0 * static_cast< double >( i ) / ySize );
277-
}
275+
if ( feedback )
276+
{
277+
feedback->setProgress( 100.0 * static_cast< double >( i ) / ySize );
278+
}
278279

279-
if ( i == 0 )
280+
if ( i == 0 )
281+
{
282+
//fill scanline 1 with (input) nodata for the values above the first row and feed scanline2 with the first row
283+
for ( int a = 0; a < xSize + 2 ; ++a )
280284
{
281-
//fill scanline 1 with (input) nodata for the values above the first row and feed scanline2 with the first row
282-
for ( int a = 0; a < xSize + 2 ; ++a )
283-
{
284-
scanLine1[a] = mInputNodataValue;
285-
}
286-
// Read scanline2
287-
if ( GDALRasterIO( rasterBand, GF_Read, 0, 0, xSize, 1, &scanLine2[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
288-
{
289-
QgsDebugMsg( "Raster IO Error" );
290-
}
285+
scanLine1[a] = mInputNodataValue;
291286
}
292-
else
287+
// Read scanline2
288+
if ( GDALRasterIO( rasterBand, GF_Read, 0, 0, xSize, 1, &scanLine2[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
293289
{
294-
//normally fetch only scanLine3 and release scanline 1 if we move forward one row
295-
CPLFree( scanLine1 );
296-
scanLine1 = scanLine2;
297-
scanLine2 = scanLine3;
298-
scanLine3 = ( float * ) CPLMalloc( sizeof( float ) * ( xSize + 2 ) );
290+
QgsDebugMsg( "Raster IO Error" );
299291
}
292+
}
293+
else
294+
{
295+
//normally fetch only scanLine3 and release scanline 1 if we move forward one row
296+
//scanLine1 = scanLine2;
297+
//scanLine2 = scanLine3;
298+
//scanLine3 = ( float * ) CPLMalloc( sizeof( float ) * ( xSize + 2 ) );
299+
scanLine1.reset( scanLine2.release() );
300+
scanLine2.reset( scanLine3.release() );
301+
scanLine3.reset( xSize + 2 );
302+
}
300303

301-
// Read scanline 3
302-
if ( i == ySize - 1 ) //fill the row below the bottom with nodata values
303-
{
304-
for ( int a = 0; a < xSize + 2; ++a )
305-
{
306-
scanLine3[a] = mInputNodataValue;
307-
}
308-
}
309-
else
304+
// Read scanline 3
305+
if ( i == ySize - 1 ) //fill the row below the bottom with nodata values
306+
{
307+
for ( int a = 0; a < xSize + 2; ++a )
310308
{
311-
if ( GDALRasterIO( rasterBand, GF_Read, 0, i + 1, xSize, 1, &scanLine3[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
312-
{
313-
QgsDebugMsg( "Raster IO Error" );
314-
}
309+
scanLine3[a] = mInputNodataValue;
315310
}
316-
// Set first and last extra colums to nodata
317-
scanLine1[0] = scanLine1[xSize + 1] = mInputNodataValue;
318-
scanLine2[0] = scanLine2[xSize + 1] = mInputNodataValue;
319-
scanLine3[0] = scanLine3[xSize + 1] = mInputNodataValue;
320-
321-
errorCode = cl::enqueueWriteBuffer( scanLine1Buffer, CL_TRUE, 0,
322-
sizeof( float ) * ( xSize + 2 ), scanLine1 );
323-
errorCode = cl::enqueueWriteBuffer( scanLine2Buffer, CL_TRUE, 0,
324-
sizeof( float ) * ( xSize + 2 ), scanLine2 );
325-
errorCode = cl::enqueueWriteBuffer( scanLine3Buffer, CL_TRUE, 0,
326-
sizeof( float ) * ( xSize + 2 ), scanLine3 );
327-
328-
kernel( cl::EnqueueArgs(
329-
cl::NDRange( xSize )
330-
),
331-
scanLine1Buffer,
332-
scanLine2Buffer,
333-
scanLine3Buffer,
334-
resultLineBuffer,
335-
rasterParamsBuffer
336-
);
337-
338-
cl::enqueueReadBuffer( resultLineBuffer, CL_TRUE, 0, xSize * sizeof( float ), resultLine );
339-
340-
if ( GDALRasterIO( outputRasterBand, GF_Write, 0, i, xSize, 1, resultLine, xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
311+
}
312+
else
313+
{
314+
if ( GDALRasterIO( rasterBand, GF_Read, 0, i + 1, xSize, 1, &scanLine3[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
341315
{
342316
QgsDebugMsg( "Raster IO Error" );
343317
}
318+
}
319+
// Set first and last extra colums to nodata
320+
scanLine1[0] = scanLine1[xSize + 1] = mInputNodataValue;
321+
scanLine2[0] = scanLine2[xSize + 1] = mInputNodataValue;
322+
scanLine3[0] = scanLine3[xSize + 1] = mInputNodataValue;
344323

324+
errorCode = cl::enqueueWriteBuffer( scanLine1Buffer, CL_TRUE, 0,
325+
sizeof( float ) * ( xSize + 2 ), scanLine1.get() );
326+
errorCode = cl::enqueueWriteBuffer( scanLine2Buffer, CL_TRUE, 0,
327+
sizeof( float ) * ( xSize + 2 ), scanLine2.get() );
328+
errorCode = cl::enqueueWriteBuffer( scanLine3Buffer, CL_TRUE, 0,
329+
sizeof( float ) * ( xSize + 2 ), scanLine3.get() );
330+
331+
kernel( cl::EnqueueArgs(
332+
cl::NDRange( xSize )
333+
),
334+
scanLine1Buffer,
335+
scanLine2Buffer,
336+
scanLine3Buffer,
337+
resultLineBuffer,
338+
rasterParamsBuffer
339+
);
340+
341+
cl::enqueueReadBuffer( resultLineBuffer, CL_TRUE, 0, xSize * sizeof( float ), resultLine.get() );
342+
343+
if ( GDALRasterIO( outputRasterBand, GF_Write, 0, i, xSize, 1, resultLine.get(), xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
344+
{
345+
QgsDebugMsg( "Raster IO Error" );
345346
}
346347
}
347-
catch ( cl::Error &e )
348-
{
349-
CPLFree( resultLine );
350-
CPLFree( scanLine1 );
351-
CPLFree( scanLine2 );
352-
CPLFree( scanLine3 );
353-
throw e;
354-
}
355348

356-
CPLFree( resultLine );
357-
CPLFree( scanLine1 );
358-
CPLFree( scanLine2 );
359-
CPLFree( scanLine3 );
360349

361350
if ( feedback && feedback->isCanceled() )
362351
{

‎src/analysis/raster/slope.cl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ float calcFirstDer( float x11, float x21, float x31, float x12, float x22, float
6868
return sum / ( weight * mCellSize ) * mZFactor;
6969
}
7070

71-
7271
__kernel void processNineCellWindow( __global float *scanLine1,
7372
__global float *scanLine2,
7473
__global float *scanLine3,

‎src/core/qgsopenclutils.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "qgsmessagelog.h"
1919
#include "qgslogger.h"
2020

21+
2122
#include <QTextStream>
2223
#include <QFile>
2324
#include <QDebug>

‎src/core/qgsopenclutils.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "qgis_core.h"
2828
#include "qgis.h"
2929

30+
#include "cpl_conv.h"
3031

3132
/**
3233
* \ingroup core
@@ -46,6 +47,62 @@ class CORE_EXPORT QgsOpenClUtils
4647
static QLatin1String LOGMESSAGE_TAG;
4748
static QString errorText( const int errorCode );
4849

50+
/**
51+
* Tiny smart-pointer wrapper around CPLMalloc and CPLFree: this is needed because
52+
* OpenCL C++ API may throw exceptions
53+
*/
54+
template <typename T>
55+
struct CPLAllocator
56+
{
57+
58+
public:
59+
60+
explicit CPLAllocator( unsigned long size ): mMem( ( T * )CPLMalloc( sizeof( T ) * size ) ) { }
61+
62+
~CPLAllocator()
63+
{
64+
CPLFree( ( void * )mMem );
65+
}
66+
67+
void reset( T *newData )
68+
{
69+
if ( mMem )
70+
CPLFree( ( void * )mMem );
71+
mMem = newData;
72+
}
73+
74+
void reset( unsigned long size )
75+
{
76+
reset( ( T * )CPLMalloc( sizeof( T ) *size ) );
77+
}
78+
79+
T &operator* ()
80+
{
81+
return &mMem[0];
82+
}
83+
84+
T *release()
85+
{
86+
T *tmpMem = mMem;
87+
mMem = nullptr;
88+
return tmpMem;
89+
}
90+
91+
T &operator[]( const int index )
92+
{
93+
return mMem[index];
94+
}
95+
96+
T *get()
97+
{
98+
return mMem;
99+
}
100+
101+
private:
102+
103+
T *mMem = nullptr;
104+
};
105+
49106
private:
50107
QgsOpenClUtils();
51108
static void init();

0 commit comments

Comments
 (0)
Please sign in to comment.