Skip to content

Commit

Permalink
OpenCL tests and aspect
Browse files Browse the repository at this point in the history
  • Loading branch information
elpaso committed Aug 8, 2018
1 parent 8ea565a commit 7404263
Show file tree
Hide file tree
Showing 8 changed files with 502 additions and 0 deletions.
114 changes: 114 additions & 0 deletions src/analysis/raster/aspect.cl
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
float calcFirstDer( float x11, float x21, float x31, float x12, float x22, float x32, float x13, float x23, float x33,
float mInputNodataValue, float mOutputNodataValue, float mZFactor, float mCellSize )
{
//the basic formula would be simple, but we need to test for nodata values...
//X: return (( (x31 - x11) + 2 * (x32 - x12) + (x33 - x13) ) / (8 * mCellSizeX));
//Y: return (((x11 - x13) + 2 * (x21 - x23) + (x31 - x33)) / ( 8 * mCellSizeY));

int weight = 0;
float sum = 0;


//first row
if ( x31 != mInputNodataValue && x11 != mInputNodataValue ) //the normal case
{
sum += ( x31 - x11 );
weight += 2;
}
else if ( x31 == mInputNodataValue && x11 != mInputNodataValue && x21 != mInputNodataValue ) //probably 3x3 window is at the border
{
sum += ( x21 - x11 );
weight += 1;
}
else if ( x11 == mInputNodataValue && x31 != mInputNodataValue && x21 != mInputNodataValue ) //probably 3x3 window is at the border
{
sum += ( x31 - x21 );
weight += 1;
}

//second row
if ( x32 != mInputNodataValue && x12 != mInputNodataValue ) //the normal case
{
sum += 2.0f * ( x32 - x12 );
weight += 4;
}
else if ( x32 == mInputNodataValue && x12 != mInputNodataValue && x22 != mInputNodataValue )
{
sum += 2.0f * ( x22 - x12 );
weight += 2;
}
else if ( x12 == mInputNodataValue && x32 != mInputNodataValue && x22 != mInputNodataValue )
{
sum += 2.0f * ( x32 - x22 );
weight += 2;
}

//third row
if ( x33 != mInputNodataValue && x13 != mInputNodataValue ) //the normal case
{
sum += ( x33 - x13 );
weight += 2;
}
else if ( x33 == mInputNodataValue && x13 != mInputNodataValue && x23 != mInputNodataValue )
{
sum += ( x23 - x13 );
weight += 1;
}
else if ( x13 == mInputNodataValue && x33 != mInputNodataValue && x23 != mInputNodataValue )
{
sum += ( x33 - x23 );
weight += 1;
}

if ( weight == 0 )
{
return mOutputNodataValue;
}

return sum / ( weight * mCellSize ) * mZFactor;
}


__kernel void processNineCellWindow( __global float *scanLine1,
__global float *scanLine2,
__global float *scanLine3,
__global float *resultLine,
__global float *rasterParams
) {

// Get the index of the current element
const int i = get_global_id(0);

// Do the operation
//return (( (x31 - x11) + 2 * (x32 - x12) + (x33 - x13) ) / (8 * mCellSizeX))
float derX = calcFirstDer( scanLine1[i], scanLine2[i], scanLine3[i],
scanLine1[i+1], scanLine2[i+1], scanLine3[i+1],
scanLine1[i+2], scanLine2[i+2], scanLine3[i+2],
rasterParams[0], rasterParams[1], rasterParams[2], rasterParams[3]
);
//return (((x11 - x13) + 2 * (x21 - x23) + (x31 - x33)) / ( 8 * mCellSizeY));
float derY = calcFirstDer( scanLine1[i+2], scanLine1[i+1], scanLine1[i],
scanLine2[i+2], scanLine2[i+1], scanLine2[i],
scanLine3[i+2], scanLine3[i+1], scanLine3[i],
rasterParams[0], rasterParams[1], rasterParams[2], rasterParams[4]
);


if ( derX == rasterParams[1] || derY == rasterParams[1] ||
( derX == 0.0f && derY == 0.0f) )
{
resultLine[i] = rasterParams[1];
}
else
{
// 180.0 / M_PI = 57.29577951308232
float aspect = atan2( derX, derY ) * 57.29577951308232;
if ( aspect < 0 )
resultLine[i] = 90.0f - aspect;
else if (aspect > 90.0f)
// 360 + 90 = 450
resultLine[i] = 450.0f - aspect;
else
resultLine[i] = 90.0 - aspect;
}
}
128 changes: 128 additions & 0 deletions src/core/qgsopenclutils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/***************************************************************************
qgsopenclutils.cpp - QgsOpenClUtils
---------------------
begin : 11.4.2018
copyright : (C) 2018 by elpaso
email : elpaso at itopen dot it
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsopenclutils.h"
#include "qgssettings.h"
#include "qgsmessagelog.h"
#include "qgslogger.h"

#include <QTextStream>
#include <QFile>
#include <QDebug>

QLatin1String QgsOpenClUtils::SETTINGS_KEY = QLatin1Literal( "OpenClEnabled" );
QLatin1String QgsOpenClUtils::LOGMESSAGE_TAG = QLatin1Literal( "OpenCL" );
std::unique_ptr<cl::Context> QgsOpenClUtils::sContext = nullptr;
bool QgsOpenClUtils::sAvailable = false;


void QgsOpenClUtils::init()
{
static bool initialized = false;
if ( ! initialized )
{
std::vector<cl::Platform> platforms;
cl::Platform::get( &platforms );
cl::Platform plat;
cl::Device dev;
for ( auto &p : platforms )
{
std::string platver = p.getInfo<CL_PLATFORM_VERSION>();
QgsDebugMsg( QStringLiteral( "Found platform %1: %2" ).arg( QString::fromStdString( platver ), QString::fromStdString( p.getInfo<CL_PLATFORM_NAME>() ) ) );
if ( platver.find( "OpenCL 1." ) != std::string::npos )
{
std::vector<cl::Device> devices;
// Check for a GPU device
p.getDevices( CL_DEVICE_TYPE_GPU, &devices );
if ( devices.size() > 0 )
{
// Got one!
plat = p;
dev = devices[0];
break;
}
}
}
if ( plat() == 0 )
{
QgsMessageLog::logMessage( QObject::tr( "No OpenCL 1.x platform with GPU found." ), LOGMESSAGE_TAG, Qgis::Warning );
sAvailable = false;
}
else
{
cl::Platform newP = cl::Platform::setDefault( plat );
if ( newP != plat )
{
QgsMessageLog::logMessage( QObject::tr( "Error setting default platform." ), LOGMESSAGE_TAG, Qgis::Warning );
sAvailable = false;
}
else
{
cl::Device::setDefault( dev );
std::vector<cl::Device> devices;
devices.push_back( cl::Device::getDefault() );
sContext = qgis::make_unique<cl::Context>( devices );
cl::Context::setDefault( *sContext );
sAvailable = true;
}
}
initialized = true;
}
}


bool QgsOpenClUtils::enabled()
{
return QgsSettings().value( SETTINGS_KEY, true, QgsSettings::Section::Core ).toBool();
}

bool QgsOpenClUtils::available()
{
init();
return sAvailable;
}

void QgsOpenClUtils::setEnabled( bool enabled )
{
QgsSettings().setValue( SETTINGS_KEY, enabled, QgsSettings::Section::Core );
}

QString QgsOpenClUtils::sourceFromPath( const QString &path )
{
// TODO: check for compatibility with current platform ( cl_khr_fp64 )
// Try to load the program sources
QString source_str;
QFile file( path );
if ( file.open( QFile::ReadOnly | QFile::Text ) )
{
QTextStream in( &file );
source_str = in.readAll();
file.close();
}
else
{
QgsMessageLog::logMessage( QObject::tr( "Could not load OpenCL program from path %1." ).arg( path ), LOGMESSAGE_TAG, Qgis::Warning );
}
return source_str;
}

QString QgsOpenClUtils::buildLog( cl::BuildError &e )
{
cl::BuildLogType build_logs = e.getBuildLog();
QString build_log;
if ( build_logs.size() > 0 )
build_log = QString::fromStdString( build_logs[0].second );
return build_log;
}
63 changes: 63 additions & 0 deletions src/core/qgsopenclutils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/***************************************************************************
qgsopenclutils.h - QgsOpenClUtils
---------------------
begin : 11.4.2018
copyright : (C) 2018 by Alessandro Pasotti
email : elpaso at itopen dot it
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSOPENCLUTILS_H
#define QGSOPENCLUTILS_H

#define SIP_NO_FILE

#define CL_HPP_ENABLE_EXCEPTIONS
#define CL_HPP_MINIMUM_OPENCL_VERSION 110
#define CL_HPP_TARGET_OPENCL_VERSION 110
#include <CL/cl2.hpp>


#include "qgis_core.h"
#include "qgis.h"

//TODO: remove
#include "qgsmessagelog.h"


/**
* \ingroup core
* \class QgsOpenClUtils
* \brief The QgsOpenClUtils class is responsible for common OpenCL operations
* \since QGIS 3.4
* \note not available in Python bindings
*/
class CORE_EXPORT QgsOpenClUtils
{
public:
static bool enabled();
static bool available();
static void setEnabled( bool enabled );
static QString buildLog( cl::BuildError &e );
static QString sourceFromPath( const QString &path );
static QLatin1String LOGMESSAGE_TAG;

private:
QgsOpenClUtils();
static void init();
static bool sAvailable;
// TODO: check if this is needed
static std::unique_ptr<cl::Context> sContext;
static QLatin1String SETTINGS_KEY;

};



#endif // QGSOPENCLUTILS_H
Loading

0 comments on commit 7404263

Please sign in to comment.