#pragma once
#if !defined( AMD_CLFFT_plan_H )
#define AMD_CLFFT_plan_H
#include <cstring>
#include "private.h"
#include "lock.h"
#include "generator.h"
std::string getKernelName(const clfftGenerators gen, const clfftPlanHandle plHandle, bool withPlHandle);
namespace ARBITRARY {
enum {
MAX_DIMS = 3,
SIMD_WIDTH = 64,
LDS_BANK_BITS = 5,
LDS_BANK_SIZE = (1 << LDS_BANK_BITS),
LDS_PADDING = false,
LDS_FRACTION_IDEAL = 6, LDS_FRACTION_MAX = 4,
LDS_COMPLEX = false,
TWIDDLE_DEE = 8,
};
};
enum BlockComputeType
{
BCT_C2C, BCT_C2R, BCT_R2C, };
enum NonSquareTransposeKernelType
{
NON_SQUARE_TRANS_PARENT,
NON_SQUARE_TRANS_TRANSPOSE_BATCHED_LEADING,
NON_SQUARE_TRANS_TRANSPOSE_BATCHED,
NON_SQUARE_TRANS_SWAP
};
enum NON_SQUARE_KERNEL_ORDER
{
NOT_A_TRANSPOSE,
SWAP_AND_TRANSPOSE, TRANSPOSE_AND_SWAP, TRANSPOSE_LEADING_AND_SWAP, };
#define CLFFT_CB_SIZE 32
#define CLFFT_MAX_INTERNAL_DIM 16
typedef struct clfftCallbackParam_
{
int localMemSize;
const char* funcname;
const char* funcstring;
}clfftCallbackParam;
struct FFTKernelGenKeyParams {
size_t fft_DataDim; size_t fft_N[CLFFT_MAX_INTERNAL_DIM]; size_t fft_inStride [CLFFT_MAX_INTERNAL_DIM]; size_t fft_outStride[CLFFT_MAX_INTERNAL_DIM];
clfftResultLocation fft_placeness;
clfftLayout fft_inputLayout;
clfftLayout fft_outputLayout;
clfftPrecision fft_precision;
double fft_fwdScale;
double fft_backScale;
size_t fft_SIMD; size_t fft_LDSsize; size_t fft_R;
size_t fft_MaxWorkGroupSize;
bool fft_3StepTwiddle; bool fft_twiddleFront;
bool fft_realSpecial; size_t fft_realSpecial_Nr;
bool fft_RCsimple;
bool transOutHorizontal;
bool blockCompute;
BlockComputeType blockComputeType;
size_t blockSIMD;
size_t blockLDS;
NonSquareTransposeKernelType nonSquareKernelType;
size_t transposeMiniBatchSize;
size_t transposeBatchSize;
NON_SQUARE_KERNEL_ORDER nonSquareKernelOrder;
bool fft_hasPreCallback;
clfftCallbackParam fft_preCallback;
bool fft_hasPostCallback;
clfftCallbackParam fft_postCallback;
cl_ulong limit_LocalMemSize;
FFTKernelGenKeyParams()
{
fft_DataDim = 0;
for(int i=0; i<CLFFT_MAX_INTERNAL_DIM; i++)
{
fft_N[i] = 0;
fft_inStride[i] = 0;
fft_outStride[i] = 0;
}
fft_placeness = CLFFT_OUTOFPLACE;
fft_inputLayout = CLFFT_COMPLEX_INTERLEAVED;
fft_outputLayout = CLFFT_COMPLEX_INTERLEAVED;
fft_precision = CLFFT_SINGLE;
fft_fwdScale = fft_backScale = 0.0;
fft_SIMD = 0;
fft_LDSsize = 0;
fft_R = 0;
fft_MaxWorkGroupSize = 0;
fft_3StepTwiddle = false;
fft_twiddleFront = false;
transOutHorizontal = false;
fft_realSpecial = false;
fft_realSpecial_Nr = 0;
fft_RCsimple = false;
blockCompute = false;
blockComputeType = BCT_C2C;
blockSIMD = 0;
blockLDS = 0;
nonSquareKernelType = NON_SQUARE_TRANS_PARENT;
transposeMiniBatchSize = 1;
transposeBatchSize = 1;
fft_hasPreCallback = false;
fft_hasPostCallback = false;
limit_LocalMemSize = 0;
}
};
bool operator<( const FFTKernelGenKeyParams& lhs, const FFTKernelGenKeyParams& rhs);
class FFTPlan;
class FFTRepo;
enum FFTActionImplID
{
FFT_DEFAULT_STOCKHAM_ACTION,
FFT_DEFAULT_TRANSPOSE_ACTION,
FFT_DEFAULT_COPY_ACTION,
FFT_STATIC_STOCKHAM_ACTION
};
struct FFTKernelSignatureHeader
{
int datasize;
FFTActionImplID id;
FFTKernelSignatureHeader(int size_, FFTActionImplID id_)
{
::memset(this, 0, size_);
datasize = size_;
id = id_;
}
};
template <typename DATA, FFTActionImplID ID>
struct FFTKernelSignature : public FFTKernelSignatureHeader, public DATA
{
FFTKernelSignature()
: FFTKernelSignatureHeader(sizeof(FFTKernelSignature<DATA, ID>), ID)
{
}
};
class FFTAction
{
public:
FFTAction(FFTPlan * plan, clfftStatus & err);
virtual clfftStatus enqueue(clfftPlanHandle plHandle,
clfftDirection dir,
cl_uint numQueuesAndEvents,
cl_command_queue* commQueues,
cl_uint numWaitEvents,
const cl_event* waitEvents,
cl_event* outEvents,
cl_mem* clInputBuffers,
cl_mem* clOutputBuffers);
protected:
virtual clfftGenerators getGenerator() = 0;
clfftStatus compileKernels ( const cl_command_queue commQueueFFT, const clfftPlanHandle plHandle, FFTPlan* fftPlan);
clfftStatus writeKernel ( const clfftPlanHandle plHandle, const clfftGenerators gen, const FFTKernelSignatureHeader* data, const cl_context& context, const cl_device_id &device);
virtual clfftStatus generateKernel ( FFTRepo & fftRepo, const cl_command_queue commQueueFFT) = 0;
virtual clfftStatus getWorkSizes ( std::vector<size_t> & globalws, std::vector<size_t> & localws) = 0;
virtual const FFTKernelSignatureHeader * getSignatureData() = 0;
FFTPlan * plan;
private:
clfftStatus selectBufferArguments(FFTPlan * plan,
cl_mem* clInputBuffers,
cl_mem* clOutputBuffers,
std::vector< cl_mem > &inputBuff,
std::vector< cl_mem > &outputBuff);
virtual bool buildForwardKernel() = 0;
virtual bool buildBackwardKernel() = 0;
};
struct FFTEnvelope {
cl_ulong limit_LocalMemSize;
size_t limit_Dimensions;
size_t limit_Size[8];
size_t limit_WorkGroupSize;
FFTEnvelope ()
: limit_LocalMemSize (0)
, limit_Dimensions (0)
, limit_WorkGroupSize (0)
{
::memset( &limit_Size, 0, sizeof( limit_Size ) );
}
};
class FFTPlan
{
public:
bool baked;
clfftDim dim;
clfftLayout inputLayout;
clfftLayout outputLayout;
clfftResultLocation placeness;
clfftResultTransposed transposed;
clfftPrecision precision;
cl_context context;
double forwardScale, backwardScale;
size_t iDist, oDist;
size_t batchsize;
cl_device_id bakeDevice;
std::vector< size_t > length;
std::vector< size_t > inStride, outStride;
FFTEnvelope envelope;
size_t tmpBufSize;
cl_mem intBuffer;
bool libCreatedIntBuffer;
size_t tmpBufSizeRC;
cl_mem intBufferRC;
size_t tmpBufSizeC2R;
cl_mem intBufferC2R;
size_t large1D;
bool large2D;
bool twiddleFront;
clfftPlanHandle planX;
clfftPlanHandle planY;
clfftPlanHandle planZ;
bool transflag;
bool transOutHorizontal;
clfftPlanHandle planTX;
clfftPlanHandle planTY;
clfftPlanHandle planTZ;
clfftPlanHandle planRCcopy;
clfftPlanHandle planCopy;
cl_mem const_buffer;
clfftGenerators gen;
bool RCsimple;
bool realSpecial;
size_t realSpecial_Nr;
bool userPlan;
bool allOpsInplace;
bool transpose_in_2d_inplace;
bool blockCompute;
BlockComputeType blockComputeType;
bool hasPreCallback;
bool hasPostCallback;
clfftCallbackParam preCallback;
clfftCallbackParam postCallbackParam;
cl_mem precallUserData;
cl_mem postcallUserData;
clfftPlanHandle plHandle;
FFTAction * action;
NonSquareTransposeKernelType nonSquareKernelType;
size_t transposeMiniBatchSize;
NON_SQUARE_KERNEL_ORDER nonSquareKernelOrder;
FFTPlan ()
: baked (false)
, dim (CLFFT_1D)
, inputLayout (CLFFT_COMPLEX_INTERLEAVED)
, outputLayout (CLFFT_COMPLEX_INTERLEAVED)
, placeness (CLFFT_INPLACE)
, transposed (CLFFT_NOTRANSPOSE)
, precision (CLFFT_SINGLE)
, context (NULL)
, forwardScale (1.0)
, backwardScale (1.0)
, iDist( 1 ), oDist( 1 )
, batchsize (1)
, tmpBufSize (0)
, intBuffer( NULL )
, libCreatedIntBuffer(false)
, tmpBufSizeRC (0)
, intBufferRC( NULL )
, tmpBufSizeC2R (0)
, intBufferC2R( NULL )
, large1D(0)
, large2D(false)
, twiddleFront(false)
, planX( 0 )
, planY( 0 )
, planZ( 0 )
, transflag(false)
, transOutHorizontal(false)
, RCsimple(false)
, realSpecial(false)
, realSpecial_Nr(0)
, userPlan(false)
, allOpsInplace(false)
, transpose_in_2d_inplace(false)
, blockCompute(false)
, blockComputeType(BCT_C2C)
, planTX( 0 )
, planTY( 0 )
, planTZ( 0 )
, planRCcopy(0)
, planCopy(0)
, const_buffer( NULL )
, gen(Stockham)
, action(0)
, nonSquareKernelType(NON_SQUARE_TRANS_PARENT)
, transposeMiniBatchSize(1)
, nonSquareKernelOrder(NOT_A_TRANSPOSE)
, plHandle(0)
, hasPreCallback(false)
, hasPostCallback(false)
{
};
size_t ElementSize() const;
clfftStatus AllocateBuffers ();
clfftStatus ReleaseBuffers ();
clfftStatus GetMax1DLength (size_t *longest ) const;
clfftStatus ConstructAndEnqueueConstantBuffers( cl_command_queue* commQueueFFT );
clfftStatus GetEnvelope (const FFTEnvelope **) const;
clfftStatus SetEnvelope ();
clfftStatus GetMax1DLengthStockham (size_t *longest ) const;
~FFTPlan ()
{
ReleaseBuffers ();
if (action != NULL)
{
delete action;
action = 0;
}
}
};
static bool Is1DPossible(size_t length, size_t large1DThreshold)
{
if (length > large1DThreshold)
return false;
if ( (length%7 == 0) && (length%5 == 0) && (length%3 == 0) )
return false;
if ( (length % 11 == 0) && ((length % 13 == 0) || (length % 7 == 0) || (length % 5 == 0) || (length % 3 == 0)) )
return false;
if ( (length % 13 == 0) && ((length % 11 == 0) || (length % 7 == 0) || (length % 5 == 0) || (length % 3 == 0)) )
return false;
return true;
}
#endif