| 452 | |
| 453 | |
| 454 | clfftStatus clfftBakePlan( clfftPlanHandle plHandle, cl_uint numQueues, cl_command_queue* commQueueFFT, |
| 455 | void (CL_CALLBACK *pfn_notify)( clfftPlanHandle plHandle, void *user_data ), void* user_data ) |
| 456 | { |
| 457 | // We do not currently support multi-GPU transforms |
| 458 | if( numQueues > 1 ) |
| 459 | return CLFFT_NOTIMPLEMENTED; |
| 460 | |
| 461 | // Notification mechanism is not set up yet; BakePlan can be called recursively to decompose higher dimension FFT's into |
| 462 | // arrays of 1d transforms, and this must be implemented to make only a single callback to the user. |
| 463 | if( pfn_notify != NULL ) |
| 464 | return CLFFT_NOTIMPLEMENTED; |
| 465 | |
| 466 | if( user_data != NULL ) |
| 467 | return CLFFT_NOTIMPLEMENTED; |
| 468 | |
| 469 | FFTRepo& fftRepo = FFTRepo::getInstance( ); |
| 470 | FFTPlan* fftPlan = NULL; |
| 471 | lockRAII* planLock = NULL; |
| 472 | |
| 473 | OPENCL_V( fftRepo.getPlan( plHandle, fftPlan, planLock ), _T( "fftRepo.getPlan failed" ) ); |
| 474 | scopedLock sLock( *planLock, _T( "clfftBakePlan" ) ); |
| 475 | |
| 476 | // if we have already baked the plan and nothing has changed since, we're done here |
| 477 | if( fftPlan->baked == true ) |
| 478 | { |
| 479 | return CLFFT_SUCCESS; |
| 480 | } |
| 481 | |
| 482 | // Store the device for which we are baking |
| 483 | clGetCommandQueueInfo(*commQueueFFT, CL_QUEUE_DEVICE, sizeof(cl_device_id), &fftPlan->bakeDevice, NULL); |
| 484 | |
| 485 | //find product of lengths |
| 486 | size_t maxLengthInAnyDim = 1; |
| 487 | switch(fftPlan->dim) |
| 488 | { |
| 489 | case CLFFT_3D: maxLengthInAnyDim = maxLengthInAnyDim > fftPlan->length[DimZ] ? maxLengthInAnyDim : fftPlan->length[DimZ]; |
| 490 | case CLFFT_2D: maxLengthInAnyDim = maxLengthInAnyDim > fftPlan->length[DimY] ? maxLengthInAnyDim : fftPlan->length[DimY]; |
| 491 | case CLFFT_1D: maxLengthInAnyDim = maxLengthInAnyDim > fftPlan->length[DimX] ? maxLengthInAnyDim : fftPlan->length[DimX]; |
| 492 | } |
| 493 | |
| 494 | const bool rc = (fftPlan->inputLayout == CLFFT_REAL) || (fftPlan->outputLayout == CLFFT_REAL); |
| 495 | |
| 496 | // upper bounds on transfrom lengths - address this in the next release |
| 497 | size_t SP_MAX_LEN = 1 << 24; |
| 498 | size_t DP_MAX_LEN = 1 << 22; |
| 499 | if((fftPlan->precision == CLFFT_SINGLE) && (maxLengthInAnyDim > SP_MAX_LEN) && rc) return CLFFT_NOTIMPLEMENTED; |
| 500 | if((fftPlan->precision == CLFFT_DOUBLE) && (maxLengthInAnyDim > DP_MAX_LEN) && rc) return CLFFT_NOTIMPLEMENTED; |
| 501 | |
| 502 | |
| 503 | // release buffers, as these will be created only in EnqueueTransform |
| 504 | if( NULL != fftPlan->intBuffer ) { OPENCL_V( clReleaseMemObject( fftPlan->intBuffer ), _T( "Failed to release internal temporary buffer" ) ); fftPlan->intBuffer = NULL; } |
| 505 | if( NULL != fftPlan->intBufferRC ) { OPENCL_V( clReleaseMemObject( fftPlan->intBufferRC ), _T( "Failed to release internal temporary buffer" ) ); fftPlan->intBufferRC = NULL; } |
| 506 | if( NULL != fftPlan->intBufferC2R ) { OPENCL_V( clReleaseMemObject( fftPlan->intBufferC2R ), _T( "Failed to release internal temporary buffer" ) ); fftPlan->intBufferC2R = NULL; } |
| 507 | |
| 508 | |
| 509 | if( fftPlan->userPlan ) // confirm it is top-level plan (user plan) |
| 510 | { |
| 511 | if(fftPlan->placeness == CLFFT_INPLACE) |